Compare commits
37 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 173ab89158 | |||
| b863dfe727 | |||
| d21f573cc5 | |||
| 8b646bf30a | |||
| 3187ccbfe1 | |||
| 6950bd15c2 | |||
| 9b4a302f6a | |||
| 36c4ae414b | |||
| 35e7602eb8 | |||
| a231bf1fe1 | |||
| eb636dbd89 | |||
| 0ec0eff90c | |||
| 26e75e093e | |||
| 99eae1fe9f | |||
| 33e9041d60 | |||
| 9760bcb00e | |||
| ed90911a5c | |||
| 4dda59a510 | |||
| b40eeb32b8 | |||
| bc47e6e5ac | |||
| 8bfca5e8f2 | |||
| fff33185b9 | |||
| 0411cd0ec1 | |||
| 08ff505b67 | |||
| 1bbbc22bcb | |||
| 76452a9c73 | |||
| a2d21e69b6 | |||
| f1d7e879ac | |||
| d75bd95e89 | |||
| 808335126f | |||
| 4b105ec88f | |||
| ee1f817dc6 | |||
| 01dabcf6b0 | |||
| 0f84e52c21 | |||
| 5d3d52496e | |||
| 75cf48f4fe | |||
| 13ad95dc23 |
196
docs/plan/NewEditor_ArchitectureClosurePlan_2026-04-22.md
Normal file
196
docs/plan/NewEditor_ArchitectureClosurePlan_2026-04-22.md
Normal file
@@ -0,0 +1,196 @@
|
||||
# NewEditor Architecture Closure Plan
|
||||
|
||||
Date: 2026-04-22
|
||||
|
||||
## 1. Objective
|
||||
|
||||
彻底收口 `new_editor` 当前仍然残留的旧语义、冗余结构和重复控制面。
|
||||
|
||||
这次不是补丁式修正,而是把当前主架构重新收成单一路径:
|
||||
|
||||
1. 主窗口 UI 渲染只保留一条 `D3D12` 实例化 primitive pass。
|
||||
2. 启动截图策略只保留一个控制源。
|
||||
3. `Rendering/Native` 这层已经失效的旧模块边界被移除。
|
||||
4. 已确认无用的死代码和错误语义命名被清理。
|
||||
|
||||
## 2. Confirmed Root Issues
|
||||
|
||||
### 2.1 D3D12 UI renderer still contains a legacy geometry sub-pipeline
|
||||
|
||||
当前 `D3D12UiRenderer` 虽然已经是 `D3D12` 主路径,但内部仍然并存两套 UI 几何编译/提交策略:
|
||||
|
||||
1. `QuadInstanced`
|
||||
2. `LegacyIndexed`
|
||||
|
||||
其中绝大多数 UI 命令已经走实例化 primitive 路径,只有少量三角形命令仍然维持整套:
|
||||
|
||||
- legacy vertex buffer
|
||||
- legacy index buffer
|
||||
- legacy pipeline state
|
||||
- legacy batch kind
|
||||
|
||||
这会导致:
|
||||
|
||||
- UI renderer 不是单一路径
|
||||
- 缓冲管理、缓存结构、绘制分发继续为旧几何方案付复杂度成本
|
||||
- “legacy” 语义真正活着,而不是只有名字没改
|
||||
|
||||
### 2.2 Startup auto-capture ownership is split across two layers
|
||||
|
||||
当前 startup capture 既在 `EditorWindowScreenshotController::Initialize(...)` 内通过环境变量触发,
|
||||
又在 `EditorWindowRuntimeController::Initialize(...)` 内通过
|
||||
`autoCaptureOnStartup + env` 触发。
|
||||
|
||||
这导致:
|
||||
|
||||
- 策略决定权不是单点
|
||||
- `autoCaptureOnStartup` 形参不是唯一真实来源
|
||||
- 非主窗口也可能被环境变量隐式触发 startup request
|
||||
|
||||
### 2.3 Rendering/Native module boundary is obsolete
|
||||
|
||||
`app/Rendering/Native/` 目录现在只剩 `AutoScreenshot.*`。
|
||||
|
||||
它已经不再承担旧的 native renderer backend 职责,但目录和 include 关系仍然保留旧时代边界。
|
||||
|
||||
### 2.4 Confirmed dead code remains in the hot renderer unit
|
||||
|
||||
`D3D12UiRenderer.cpp` 里存在已无调用方的辅助函数,说明之前的旧几何阶段没有清理彻底。
|
||||
|
||||
## 3. Target End State
|
||||
|
||||
完成后应满足:
|
||||
|
||||
1. `D3D12UiRenderer` 不再存在 `LegacyIndexed` / `legacy*` 动态几何资源。
|
||||
2. 所有 UI draw command 都编译为同一类实例化 primitive 数据。
|
||||
3. 渲染时只绑定一套 UI primitive pipeline。
|
||||
4. `EditorWindowScreenshotController` 不再自行读取 startup env,也不再拥有策略判断权。
|
||||
5. startup capture 是否发生,只由窗口创建策略单点决定。
|
||||
6. `Rendering/Native` 目录被清空或完全移除。
|
||||
7. 已确认无调用的渲染死代码删除。
|
||||
|
||||
## 4. Refactor Strategy
|
||||
|
||||
### Phase A. Collapse UI geometry into one primitive pipeline
|
||||
|
||||
把当前 UI pass 改成单一实例化 primitive 方案:
|
||||
|
||||
- 保留单位 quad carrier vertex/index buffer
|
||||
- 删除动态 legacy vertex/index buffer
|
||||
- 删除 legacy pipeline state
|
||||
- 删除 legacy batch kind
|
||||
- 统一 batch 为 instance range + texture + scissor
|
||||
|
||||
需要新增的 primitive 能力:
|
||||
|
||||
- 现有 rect / outline / circle / text / image / gradient
|
||||
- 新增 triangle primitive,让 `FilledTriangle` 也走实例化路径
|
||||
|
||||
triangle 的正确实现目标:
|
||||
|
||||
- 不是回退到 indexed geometry
|
||||
- 不是临时特判 draw call
|
||||
- 而是作为实例化 primitive 的一种 kind,被统一编译、缓存、上传和绘制
|
||||
|
||||
### Phase B. Rebuild renderer data model around the unified path
|
||||
|
||||
同步调整:
|
||||
|
||||
- `UiBatchKind` 去除或退化
|
||||
- `UiQuadInstance` 升级为更通用的 `UiPrimitiveInstance`
|
||||
- `CompiledDrawList` 不再缓存 legacy vertices / indices
|
||||
- `EnsureFrameBufferCapacity(...)` 只维护 primitive instance buffer
|
||||
- render dispatch 只保留单一 pipeline bind 分支
|
||||
|
||||
### Phase C. Collapse startup capture ownership to one source of truth
|
||||
|
||||
把 startup capture 的策略权上移并单点化:
|
||||
|
||||
- `Application` 或窗口创建层读取 env / policy
|
||||
- `CreateParams.autoCaptureOnStartup` 成为唯一窗口级输入
|
||||
- `EditorWindowRuntimeController` 只消费该参数
|
||||
- `EditorWindowScreenshotController` 只做请求/路径/结果管理,不做策略判断
|
||||
|
||||
### Phase D. Remove obsolete Native module shell
|
||||
|
||||
将截图控制器从 `app/Rendering/Native/` 迁移到更合理的位置,
|
||||
预计是窗口运行时或通用 support/capture 模块。
|
||||
|
||||
要求:
|
||||
|
||||
- 迁移后 active include 不再引用 `Rendering/Native`
|
||||
- `new_editor/CMakeLists.txt` 同步更新
|
||||
|
||||
### Phase E. Delete dead helpers and normalize semantics
|
||||
|
||||
删除已经确认无调用的旧辅助函数,并统一命名:
|
||||
|
||||
- `legacy*` -> 按真实职责改名,或随着删除一起消失
|
||||
- 清理无用 helper
|
||||
- 保证 renderer 术语与当前架构一致
|
||||
|
||||
## 5. File-Level Work
|
||||
|
||||
### 5.1 UI renderer core
|
||||
|
||||
Primary:
|
||||
|
||||
- `new_editor/app/Rendering/D3D12/D3D12UiRenderer.h`
|
||||
- `new_editor/app/Rendering/D3D12/D3D12UiRenderer.cpp`
|
||||
|
||||
### 5.2 Startup capture boundary
|
||||
|
||||
Primary:
|
||||
|
||||
- `new_editor/app/Bootstrap/Application.cpp`
|
||||
- `new_editor/app/Platform/Win32/EditorWindow.cpp`
|
||||
- `new_editor/app/Platform/Win32/EditorWindowRuntimeController.h`
|
||||
- `new_editor/app/Platform/Win32/EditorWindowRuntimeController.cpp`
|
||||
- `new_editor/app/Platform/Win32/EditorWindowManager.h`
|
||||
|
||||
### 5.3 Screenshot controller relocation
|
||||
|
||||
Current source:
|
||||
|
||||
- `new_editor/app/Platform/Win32/EditorWindowScreenshotController.h`
|
||||
- `new_editor/app/Platform/Win32/EditorWindowScreenshotController.cpp`
|
||||
|
||||
Target:
|
||||
|
||||
- move into non-legacy module location
|
||||
|
||||
### 5.4 Build graph cleanup
|
||||
|
||||
- `new_editor/CMakeLists.txt`
|
||||
|
||||
## 6. Validation
|
||||
|
||||
### 6.1 Structural validation
|
||||
|
||||
完成后搜索应满足:
|
||||
|
||||
- no `LegacyIndexed` in active UI renderer
|
||||
- no `m_legacyPipelineState`
|
||||
- no `legacyVertexBuffer`
|
||||
- no `legacyIndexBuffer`
|
||||
- no `app/Rendering/Native/AutoScreenshot.*` active include path
|
||||
|
||||
### 6.2 Runtime validation
|
||||
|
||||
必须验证:
|
||||
|
||||
1. `XCUIEditorApp` Debug 构建通过
|
||||
2. editor 正常启动
|
||||
3. 主窗口 UI 正常显示与交互
|
||||
4. startup auto-capture 正常生成
|
||||
5. detached window 不会错误触发 startup capture
|
||||
|
||||
## 7. Completion Criteria
|
||||
|
||||
只有满足以下条件,这个 plan 才算真正收口:
|
||||
|
||||
1. UI 渲染路径内部不再存在旧几何子管线
|
||||
2. startup capture 策略控制权单点化
|
||||
3. 旧 `Native` 模块边界消失
|
||||
4. 死代码删除
|
||||
5. 构建、启动、截图验证全部通过
|
||||
@@ -0,0 +1,274 @@
|
||||
# NewEditor D3D12 Legacy D2D Closure Plan
|
||||
|
||||
Date: 2026-04-22
|
||||
|
||||
## 1. Problem Statement
|
||||
|
||||
`new_editor` main-window realtime presentation has already moved onto the native `D3D12` path, but the codebase still retains a legacy `D2D / D3D11On12` bridge in the host layer.
|
||||
|
||||
That residual path is no longer the main realtime hot path, but it is still architecturally serious because it keeps a second rendering/composition implementation alive for the same UI draw model.
|
||||
|
||||
Current residual seam:
|
||||
|
||||
- `app/Rendering/Native/NativeRenderer.*`
|
||||
- `app/Rendering/D3D12/D3D12WindowInteropContext.*`
|
||||
- `app/Rendering/D3D12/D3D12WindowInteropHelpers.h`
|
||||
- host/build references that still compile and link the old bridge
|
||||
|
||||
## 2. Confirmed Current Facts
|
||||
|
||||
### 2.1 Main window realtime presentation no longer depends on D2D
|
||||
|
||||
Main realtime presentation flows through:
|
||||
|
||||
- `D3D12WindowRenderer`
|
||||
- `D3D12UiRenderer`
|
||||
- `D3D12WindowRenderLoop`
|
||||
|
||||
The active main path does not call `NativeRenderer::Render(...)`.
|
||||
|
||||
### 2.2 Residual D2D bridge is concentrated, not scattered
|
||||
|
||||
The old bridge is now effectively concentrated in:
|
||||
|
||||
- screenshot/export flow
|
||||
- dead hwnd-native D2D window rendering code that is no longer wired into the main frame loop
|
||||
|
||||
### 2.3 NativeRenderer is no longer the main texture host
|
||||
|
||||
`TexturePort` for the active editor path is already `D3D12UiTextureHost`.
|
||||
|
||||
This means the remaining `NativeRenderer` responsibilities can be removed instead of preserved as an active subsystem.
|
||||
|
||||
## 3. Root Architectural Issue
|
||||
|
||||
The root issue is not “some D2D symbols still exist”.
|
||||
|
||||
The root issue is that `new_editor` still retains two incompatible host-side ways to turn UI output into pixels:
|
||||
|
||||
1. Active path: native `D3D12` rendering into the swapchain backbuffer.
|
||||
2. Residual path: `UIDrawData -> D2D replay`, with optional `D3D11On12` resource interop.
|
||||
|
||||
As long as both remain alive:
|
||||
|
||||
- draw semantics can drift between live output and capture/export output
|
||||
- future UI/rendering changes must be kept compatible with two host backends
|
||||
- dead-window code remains available to be accidentally reused
|
||||
- build/link dependencies preserve obsolete platform coupling
|
||||
|
||||
So the correct goal is full single-path closure, not incremental patching.
|
||||
|
||||
## 4. Target End State
|
||||
|
||||
After this refactor:
|
||||
|
||||
1. Main-window realtime rendering remains native `D3D12`.
|
||||
2. Main-window screenshot capture also uses native `D3D12` backbuffer capture.
|
||||
3. `new_editor` no longer contains any host-side `D3D11On12` or `D2D` bridge code for the main window.
|
||||
4. Old hwnd `D2D` renderer code is deleted, not merely disconnected.
|
||||
5. `XCUIEditorHost` no longer compiles obsolete interop units.
|
||||
6. Host link dependencies only retain what is still genuinely required.
|
||||
|
||||
## 5. Non-Goals
|
||||
|
||||
- Do not roll the editor back to `D2D`.
|
||||
- Do not reintroduce a fallback composition backend.
|
||||
- Do not change the active `D3D12UiRenderer` architecture back into draw-data replay through another API.
|
||||
- Do not remove `DirectWrite` from `D3D12UiTextSystem`; text shaping/raster generation remains valid there.
|
||||
|
||||
## 6. Refactor Strategy
|
||||
|
||||
### Phase A. Replace screenshot bridge with native D3D12 capture
|
||||
|
||||
Introduce a native `D3D12` capture path that reads the final swapchain backbuffer and writes PNG through CPU-side WIC encoding.
|
||||
|
||||
This capture path must:
|
||||
|
||||
- capture the final composited editor frame
|
||||
- avoid `UIDrawData` replay
|
||||
- avoid `D3D11On12`
|
||||
- avoid `D2D`
|
||||
- operate on the same swapchain backbuffer the user actually sees
|
||||
|
||||
Preferred integration point:
|
||||
|
||||
- after UI rendering has finished for the active backbuffer
|
||||
- after the frame has been submitted to the queue
|
||||
- before `PresentFrame()`
|
||||
|
||||
Reason:
|
||||
|
||||
- the frame is already fully rendered
|
||||
- the current backbuffer is still the one about to be presented
|
||||
- capture remains aligned with the user-visible final image
|
||||
|
||||
### Phase B. Collapse screenshot orchestration around the active D3D12 path
|
||||
|
||||
Rework `AutoScreenshotController` so it only:
|
||||
|
||||
- tracks pending capture requests
|
||||
- resolves output/history paths
|
||||
- finalizes success/error summaries
|
||||
|
||||
It must no longer own the rendering backend choice.
|
||||
|
||||
### Phase C. Delete obsolete NativeRenderer window-render path
|
||||
|
||||
Delete the old hwnd `D2D` window renderer behavior:
|
||||
|
||||
- `Initialize(HWND)`
|
||||
- `Resize(...)`
|
||||
- `Render(...)`
|
||||
- hwnd render-target management
|
||||
- D2D draw command replay entrypoint for window presentation
|
||||
|
||||
If a remaining utility is still needed after this phase, it must live in a narrowly-scoped replacement component, not inside a zombie renderer class.
|
||||
|
||||
### Phase D. Delete D3D11On12 interop bridge
|
||||
|
||||
Once native `D3D12` capture is live:
|
||||
|
||||
- delete `D3D12WindowInteropContext.*`
|
||||
- delete `D3D12WindowInteropHelpers.h`
|
||||
- delete all `NativeRenderer` interop code
|
||||
|
||||
### Phase E. Build and link closure
|
||||
|
||||
Update host build definitions so obsolete units and libraries are removed.
|
||||
|
||||
Expected removals if no remaining consumer exists:
|
||||
|
||||
- `app/Rendering/Native/NativeRenderer.cpp`
|
||||
- `app/Rendering/D3D12/D3D12WindowInteropContext.cpp`
|
||||
- `d2d1.lib`
|
||||
- `d3d11.lib`
|
||||
|
||||
Expected retained dependencies:
|
||||
|
||||
- `d3d12.lib`
|
||||
- `d3dcompiler.lib`
|
||||
- `dwrite.lib`
|
||||
- `dxgi.lib`
|
||||
- `windowscodecs.lib`
|
||||
|
||||
## 7. Concrete File-Level Work
|
||||
|
||||
### 7.1 Add new native capture unit
|
||||
|
||||
Add new host-side unit(s), likely under `app/Rendering/D3D12/`:
|
||||
|
||||
- `D3D12WindowCapture.h`
|
||||
- `D3D12WindowCapture.cpp`
|
||||
|
||||
Responsibilities:
|
||||
|
||||
- copy current swapchain backbuffer to readback
|
||||
- map CPU pixels
|
||||
- encode PNG via WIC
|
||||
- return rich error text
|
||||
|
||||
### 7.2 Extend window renderer / render loop
|
||||
|
||||
Modify:
|
||||
|
||||
- `app/Rendering/D3D12/D3D12WindowRenderer.h`
|
||||
- `app/Rendering/D3D12/D3D12WindowRenderer.cpp`
|
||||
- `app/Rendering/D3D12/D3D12WindowRenderLoop.h`
|
||||
- `app/Rendering/D3D12/D3D12WindowRenderLoop.cpp`
|
||||
|
||||
Needed changes:
|
||||
|
||||
- expose a native capture operation on the active backbuffer
|
||||
- extend present result with capture outcome
|
||||
- allow present flow to execute capture before `PresentFrame()`
|
||||
|
||||
### 7.3 Rework screenshot controller boundary
|
||||
|
||||
Modify:
|
||||
|
||||
- `app/Rendering/Native/AutoScreenshot.h`
|
||||
- `app/Rendering/Native/AutoScreenshot.cpp`
|
||||
- `app/Platform/Win32/EditorWindowRuntimeController.h`
|
||||
- `app/Platform/Win32/EditorWindowRuntimeController.cpp`
|
||||
- `app/Platform/Win32/EditorWindow.cpp`
|
||||
|
||||
Needed changes:
|
||||
|
||||
- stop passing `UIDrawData` into screenshot rendering
|
||||
- stop depending on `NativeRenderer`
|
||||
- move screenshot triggering into the D3D12 present path
|
||||
|
||||
### 7.4 Delete obsolete renderer/interop code
|
||||
|
||||
Delete if fully unreferenced after the above:
|
||||
|
||||
- `app/Rendering/Native/NativeRenderer.h`
|
||||
- `app/Rendering/Native/NativeRenderer.cpp`
|
||||
- `app/Rendering/Native/NativeRendererHelpers.h`
|
||||
- `app/Rendering/D3D12/D3D12WindowInteropContext.h`
|
||||
- `app/Rendering/D3D12/D3D12WindowInteropContext.cpp`
|
||||
- `app/Rendering/D3D12/D3D12WindowInteropHelpers.h`
|
||||
|
||||
### 7.5 Build-system cleanup
|
||||
|
||||
Modify:
|
||||
|
||||
- `new_editor/CMakeLists.txt`
|
||||
|
||||
Remove:
|
||||
|
||||
- old source units
|
||||
- dead link libraries
|
||||
|
||||
## 8. Validation Requirements
|
||||
|
||||
### 8.1 Build validation
|
||||
|
||||
Must build:
|
||||
|
||||
- `XCUIEditorHost`
|
||||
- `XCUIEditorAppLib`
|
||||
- `XCUIEditorApp`
|
||||
|
||||
### 8.2 Runtime validation
|
||||
|
||||
Must validate:
|
||||
|
||||
1. editor launches normally
|
||||
2. main window still presents correctly
|
||||
3. manual screenshot still succeeds
|
||||
4. startup auto-capture still succeeds if enabled
|
||||
5. no screenshot path closes or stalls the main window unexpectedly
|
||||
|
||||
### 8.3 Structural validation
|
||||
|
||||
Searches after completion must show:
|
||||
|
||||
- no `NativeRenderer` references in `new_editor/app`
|
||||
- no `D3D12WindowInteropContext` references in `new_editor`
|
||||
- no `D3D11On12` references in `new_editor`
|
||||
- no `ID2D` / `D2D1` references in `new_editor/app`
|
||||
|
||||
Exception:
|
||||
|
||||
- `DirectWrite` references inside `D3D12UiTextSystem` remain allowed
|
||||
|
||||
## 9. Execution Order
|
||||
|
||||
1. Add native `D3D12` backbuffer capture path.
|
||||
2. Route `AutoScreenshotController` through that new path.
|
||||
3. Remove runtime-controller dependence on `NativeRenderer`.
|
||||
4. Delete `NativeRenderer` and `D3D12WindowInteropContext`.
|
||||
5. Clean CMake/link dependencies.
|
||||
6. Build and smoke-test.
|
||||
7. Run structural grep validation.
|
||||
|
||||
## 10. Success Criteria
|
||||
|
||||
This plan is complete only if all of the following are true:
|
||||
|
||||
- screenshots come from the native `D3D12` backbuffer path
|
||||
- no main-window host rendering code path can fall back to `D2D`
|
||||
- no `D3D11On12` bridge remains in `new_editor`
|
||||
- old dead window-render code is physically removed
|
||||
- build and smoke validation pass
|
||||
@@ -0,0 +1,146 @@
|
||||
# NewEditor UI Text Measurement Semantic Unification Plan
|
||||
|
||||
Date: `2026-04-22`
|
||||
|
||||
## Goal
|
||||
|
||||
Refactor the shared `new_editor` UI widget layer so text measurement, layout sizing, draw positioning and hit-test geometry stop sharing ambiguous width fields.
|
||||
|
||||
This is not a symptom patch.
|
||||
This is a semantic cleanup of the shared UI model.
|
||||
|
||||
## Root Problem
|
||||
|
||||
The shared widget layer currently mixes multiple width meanings under vague names such as:
|
||||
|
||||
- `desiredLabelWidth`
|
||||
- `desiredShortcutWidth`
|
||||
- `desiredWidth`
|
||||
|
||||
Across different controls, those fields are used as one or more of:
|
||||
|
||||
- measured glyph advance
|
||||
- padded control width input
|
||||
- arranged rect width surrogate
|
||||
- draw-time text positioning basis
|
||||
|
||||
That breaks the semantic boundary between:
|
||||
|
||||
- text measurement
|
||||
- layout width solving
|
||||
- final arranged geometry
|
||||
- draw clipping and hit testing
|
||||
|
||||
The `tab strip` bug was only one visible symptom of this broader design problem.
|
||||
|
||||
## Confirmed Shared Impacted Controls
|
||||
|
||||
- `new_editor/include/XCEditor/Collections/UIEditorTabStrip.h`
|
||||
- `new_editor/include/XCEditor/Menu/UIEditorMenuBar.h`
|
||||
- `new_editor/include/XCEditor/Menu/UIEditorMenuPopup.h`
|
||||
- `new_editor/include/XCEditor/Shell/UIEditorStatusBar.h`
|
||||
- `new_editor/include/XCEditor/Viewport/UIEditorViewportSlot.h`
|
||||
|
||||
Confirmed propagation paths:
|
||||
|
||||
- `new_editor/src/Shell/UIEditorShellInteraction.cpp`
|
||||
- `new_editor/src/Shell/UIEditorShellCompose.cpp`
|
||||
- `new_editor/src/Workspace/UIEditorWorkspaceCompose.cpp`
|
||||
- `new_editor/src/Workspace/UIEditorWorkspaceInteraction.cpp`
|
||||
- `new_editor/src/Viewport/UIEditorViewportShell.cpp`
|
||||
- `new_editor/src/Docking/UIEditorDockHost.cpp`
|
||||
|
||||
## End State
|
||||
|
||||
All shared text-bearing widgets must follow one rule:
|
||||
|
||||
- model fields store measured text width only
|
||||
- layout derives padded control width from measured text width
|
||||
- arranged rects remain the only source of final geometry
|
||||
- draw and hit-test consume arranged rects plus measured text width, never repurposed control widths
|
||||
|
||||
## Refactor Principles
|
||||
|
||||
- Use one semantic name for one meaning.
|
||||
- Do not reuse a measured text width field as a control width field.
|
||||
- Do not let individual widgets invent incompatible width semantics.
|
||||
- Push actual text measurement to request/model build points where a `UIEditorTextMeasurer` is available.
|
||||
- Keep estimated glyph-width fallback only as a fallback, not the primary semantic.
|
||||
|
||||
## Workstream A: Introduce Shared Text-Width Semantics
|
||||
|
||||
Required changes:
|
||||
|
||||
- add shared helper(s) for resolving measured text width from:
|
||||
- cached measured width
|
||||
- `UIEditorTextMeasurer`
|
||||
- estimated glyph fallback
|
||||
- document the semantic contract in the shared widget structs
|
||||
|
||||
Acceptance:
|
||||
|
||||
- shared controls no longer expose ambiguous width names for pure text measurement
|
||||
|
||||
## Workstream B: Normalize Shared Widget Models
|
||||
|
||||
Required changes:
|
||||
|
||||
- convert the following fields to explicit measured-text semantics:
|
||||
- `UIEditorTabStripItem`
|
||||
- `UIEditorMenuBarItem`
|
||||
- `UIEditorMenuPopupItem`
|
||||
- `UIEditorStatusBarSegment`
|
||||
- `UIEditorViewportSlotToolItem`
|
||||
- update each widget so layout derives control width from measured text width locally
|
||||
|
||||
Acceptance:
|
||||
|
||||
- measurement/layout/draw code paths in those widgets are semantically aligned
|
||||
|
||||
## Workstream C: Push Real Measurement Through Shared Request Paths
|
||||
|
||||
Required changes:
|
||||
|
||||
- shell interaction:
|
||||
- measure menu bar items
|
||||
- measure popup labels and shortcuts
|
||||
- measure shell status-bar segments
|
||||
- workspace / viewport compose:
|
||||
- measure viewport tool-item labels
|
||||
- measure viewport status-bar segments
|
||||
- carry the measured viewport shell model through compose/frame so append uses the same measured data as layout
|
||||
|
||||
Acceptance:
|
||||
|
||||
- top-level editor shell and external viewport chrome no longer rely on ad-hoc estimated widths in the steady state
|
||||
|
||||
## Workstream D: Regression Validation
|
||||
|
||||
Required checks:
|
||||
|
||||
- build `XCUIEditorLib`
|
||||
- build `XCUIEditorAppLib`
|
||||
- build `XCUIEditorApp`
|
||||
- smoke-launch `build/new_editor/Debug/XCUIEditor.exe`
|
||||
|
||||
Manual follow-up target:
|
||||
|
||||
- verify long/short mixed menu labels
|
||||
- verify long tab labels
|
||||
- verify status-bar and viewport toolbar labels remain aligned after measurement unification
|
||||
|
||||
## Out Of Scope For This Pass
|
||||
|
||||
- tree/list/property-grid virtualization
|
||||
- scene rendering optimization
|
||||
- renderer backend work
|
||||
- visual redesign
|
||||
|
||||
## Success Criteria
|
||||
|
||||
This pass is complete only if:
|
||||
|
||||
- the shared widget layer uses one consistent measured-text semantic
|
||||
- layout width derivation is local and explicit
|
||||
- shell/workspace/viewport request paths feed measured text widths into shared widgets
|
||||
- the tab fix becomes one instance of a general rule, not a special case
|
||||
271
docs/used/NewEditor_审查遗留总收口计划_2026-04-19.md
Normal file
271
docs/used/NewEditor_审查遗留总收口计划_2026-04-19.md
Normal file
@@ -0,0 +1,271 @@
|
||||
# NewEditor 审查遗留总收口计划
|
||||
|
||||
## 背景
|
||||
|
||||
当前 `new_editor` 已完成旧 `editor` / ImGui 依赖切离,也完成了 Scene、Project、Hierarchy、Win32 宿主、多窗口、测试体系等多轮迁移与重构。但从现状审查结果看,仍有一整组未收口的结构问题,它们彼此关联,不能只挑一部分处理:
|
||||
|
||||
1. `include/XCEditor` 的公共头并没有稳定地充当接口层,而是在持续聚合具体实现域。
|
||||
2. `new_editor/src` 与 `new_editor/app` 的拆分标准不一致,出现“过碎薄文件”和“超大职责文件”并存。
|
||||
3. `EditorShellRuntime` 仍是 feature 编排、状态汇总、事件中转、渲染协调、指针捕获决策的中心大对象。
|
||||
4. `EditorWindow` 与 Win32 controller 的 ownership 没有真正收拢,仍保留大量私有转发行为与跨对象透权。
|
||||
5. 平台层仍直接依赖上层 UI 语义与 theme / panel registry 等对象,平台宿主隔离未彻底完成。
|
||||
6. `ProjectPanel` 仍然是严重超载的 feature,树、网格、布局、命令、菜单、拖放、重命名全部耦合在一起。
|
||||
7. `HierarchyPanel`、`InspectorPanel`、Scene feature 的边界虽然比 `ProjectPanel` 清楚,但仍缺少统一 feature event 契约。
|
||||
8. `WorkspaceEventSync` 仍是 feature event 到 `EditorContext` / runtime 的临时胶水,而不是正式 app-level 事件入口。
|
||||
9. Scene gizmo / viewport 相关实现仍有大块高复杂度单体文件,后续会持续阻碍维护与验证。
|
||||
|
||||
这些问题的根因不是“代码多”本身,而是边界定义、文件粒度、ownership、公共接口层设计都还没有稳定下来。
|
||||
|
||||
## 本计划覆盖的全部未收口问题
|
||||
|
||||
### 一. 公共接口层失真
|
||||
|
||||
问题:
|
||||
|
||||
1. `UIEditorTheme.h` 等公共头直接吸入 list / tree / field / dock / shell / viewport 具体类型。
|
||||
2. `UIEditorWorkspaceCompose.h` 同时承载 compose types、update API、append API,并直接依赖 dock host、panel host、viewport shell。
|
||||
3. 一些 `XCEditor` 头更像“实现域聚合入口”而不是“稳定公共接口”。
|
||||
|
||||
根因:
|
||||
|
||||
- 公共头、契约头、实现头没有分层。
|
||||
- 迁移阶段用聚合头降低了接线成本,但没有在后续回收。
|
||||
|
||||
收口动作:
|
||||
|
||||
1. 将公共头拆成 `types/contracts` 与 `ops/services` 两层。
|
||||
2. 公共头只保留稳定数据结构、前置声明、轻量枚举和必要查询接口。
|
||||
3. 将 update / resolve / append / interaction 这类依赖实现细节的 API 下沉到独立 ops 头。
|
||||
4. 全量清理 `new_editor/app` 与 `tests/UI/Editor` 的 include 面。
|
||||
|
||||
验收:
|
||||
|
||||
- `XCEditor` 主要公共头不再通过一层 include 拉入整片实现域。
|
||||
- 任一 feature 引入 theme / compose 合同时,不再被动依赖大量 widget/field/shell 类型。
|
||||
|
||||
### 二. 文件粒度标准失控
|
||||
|
||||
问题:
|
||||
|
||||
1. 某些文件过碎,只剩几行转发或包装,没有形成独立 ownership。
|
||||
2. 某些文件又持续膨胀到数百上千行,承载多个变化理由。
|
||||
3. `new_editor` 的拆分策略与 `engine` 主体并不一致,当前粒度不稳定。
|
||||
|
||||
典型表现:
|
||||
|
||||
1. `EditorWindowTitleBarRendering.cpp` 这类纯转发薄文件。
|
||||
2. `ProjectPanel.cpp`、`SceneViewportTransformGizmoSupport.cpp`、`EditorWindowChromeController.cpp` 这类超大文件。
|
||||
|
||||
根因:
|
||||
|
||||
- 一部分文件是重构中间态,没有在边界明确后回收。
|
||||
- 拆分依据偏向“临时改动落点”,而不是“稳定职责边界”。
|
||||
|
||||
收口动作:
|
||||
|
||||
1. 建立明确拆分标准:按 ownership、状态归属、修改耦合、测试边界拆,不按函数数量拆。
|
||||
2. 回收纯转发薄文件,合并到真正拥有行为的实现文件。
|
||||
3. 将超大文件按真实子域拆开,而不是继续切更多壳文件。
|
||||
|
||||
验收:
|
||||
|
||||
- 不再存在大量只做单纯转发的宿主文件。
|
||||
- 大文件拆分后每个子文件都对应稳定责任,而不是“某个大文件的一个切片”。
|
||||
|
||||
### 三. EditorShellRuntime 中心化过重
|
||||
|
||||
问题:
|
||||
|
||||
1. `EditorShellRuntime` 同时拥有 panel feature、viewport host、built-in icons、pointer ownership、workspace trace。
|
||||
2. 它直接暴露 `HierarchyPanel::Event`、`ProjectPanel::Event` 等 feature-specific 细节。
|
||||
3. 顶层 runtime 既是编排器,又是状态中转站,又承担 feature 间粘合。
|
||||
|
||||
根因:
|
||||
|
||||
- 缺少统一 feature contract。
|
||||
- feature 输出和 app-level 输出没有分层。
|
||||
|
||||
收口动作:
|
||||
|
||||
1. 提取统一 feature presentation / interaction / event contract。
|
||||
2. 让 `EditorShellRuntime` 只承担编排与生命周期,不再泄露具体 panel 事件容器。
|
||||
3. 让 pointer capture / hosted content cursor / shell interaction 聚合为统一 runtime 输出模型。
|
||||
|
||||
验收:
|
||||
|
||||
- `EditorShellRuntime` 对外只暴露 app-level 结果,不直接透出具体 panel 类型。
|
||||
- 新增 feature 时不需要继续给 runtime 增加一组定制 getter。
|
||||
|
||||
### 四. Win32 宿主 ownership 不清
|
||||
|
||||
问题:
|
||||
|
||||
1. `EditorWindow` 仍保留大量窗口、输入、渲染、DPI、capture、chrome、workspace 行为。
|
||||
2. controller 已经存在,但很多只是借 `friend` 操作 `EditorWindow` 内部状态。
|
||||
3. 宿主与 controller 同时拥有职责,边界不稳定。
|
||||
|
||||
根因:
|
||||
|
||||
- controller 是从大对象里抽出来的,但 `EditorWindow` 自身没有同步瘦身。
|
||||
- 共享状态 contract 未明确,导致继续透权。
|
||||
|
||||
收口动作:
|
||||
|
||||
1. 重新定义 `EditorWindow` 的职责,只保留 HWND / message / facade /生命周期入口。
|
||||
2. 将输入、chrome、frame orchestration、runtime 更新的实际 ownership 下沉到 controller。
|
||||
3. 用明确 state contract 替代大面积 `friend` 与私有转发。
|
||||
4. 清理薄转发 cpp 文件。
|
||||
|
||||
验收:
|
||||
|
||||
- `EditorWindow.h` 私有方法数量显著下降。
|
||||
- controller 不再依赖大量跨域私有入口。
|
||||
|
||||
### 五. 平台层反向依赖 UI 语义
|
||||
|
||||
问题:
|
||||
|
||||
1. `EditorWindowChromeController` 仍直接依赖 `UIEditorTheme`、`UIEditorPanelRegistry` 等上层 UI 类型。
|
||||
2. 平台层对“标题栏显示什么 tab、什么 panel title、什么 theme metrics”知道得太多。
|
||||
|
||||
根因:
|
||||
|
||||
- 宿主 chrome 渲染逻辑仍混入编辑器语义,而不是依赖独立的宿主展示 contract。
|
||||
|
||||
收口动作:
|
||||
|
||||
1. 提取宿主 chrome 所需的独立 presentation contract。
|
||||
2. 平台层只消费宿主展示结果,不直接查询 panel registry 或 theme 聚合头。
|
||||
3. 将 detached tab/title 的编辑器语义计算上移到 app/runtime 层。
|
||||
|
||||
验收:
|
||||
|
||||
- `app/Platform/Win32` 不再直接 include 聚合 UI 头来计算编辑器展示语义。
|
||||
|
||||
### 六. ProjectPanel 职责堆积
|
||||
|
||||
问题:
|
||||
|
||||
1. `ProjectPanel` 同时管理 tree、grid、breadcrumb、rename、context menu、drag/drop、命令路由、命中测试、布局。
|
||||
2. 头文件里聚集了大量私有子域结构与帮助函数。
|
||||
3. 后续任何功能调整都会继续把该类推大。
|
||||
|
||||
根因:
|
||||
|
||||
- Project feature 尚未形成独立子域。
|
||||
- 之前为尽快打通真实行为,把所有逻辑先集中放进了主 panel。
|
||||
|
||||
收口动作:
|
||||
|
||||
1. 提取 layout / hit test 子域。
|
||||
2. 提取 breadcrumb / grid presentation 子域。
|
||||
3. 提取 context menu / rename / command target 子域。
|
||||
4. 提取 tree-grid drag/drop 协调子域。
|
||||
5. `ProjectPanel` 只保留 runtime 注入、focus 编排、事件汇总。
|
||||
|
||||
验收:
|
||||
|
||||
- `ProjectPanel.h/.cpp` 不再承载全部 UI 子域细节。
|
||||
- Project feature 的每个子文件都有明确 ownership。
|
||||
|
||||
### 七. Feature 事件模型不统一
|
||||
|
||||
问题:
|
||||
|
||||
1. `HierarchyPanel`、`ProjectPanel` 使用各自的局部 event 结构。
|
||||
2. Scene / Inspector 也在各自路径里用专有交互结果。
|
||||
3. 顶层同步逻辑必须知道每个 feature 的细节。
|
||||
|
||||
根因:
|
||||
|
||||
- 缺少统一的 app event 契约和 feature output 契约。
|
||||
|
||||
收口动作:
|
||||
|
||||
1. 定义统一 `EditorAppEvent` 或等价契约。
|
||||
2. feature 局部事件先映射为 app event,再由同步入口消费。
|
||||
3. 保留 feature 内部私有状态,但不再将私有事件结构外泄。
|
||||
|
||||
验收:
|
||||
|
||||
- 顶层不再显式依赖多个 feature-specific event 类型。
|
||||
|
||||
### 八. WorkspaceEventSync 仍是临时胶水
|
||||
|
||||
问题:
|
||||
|
||||
1. `WorkspaceEventSync` 直接读 panel event,再同步 `EditorContext` / `SceneRuntime`。
|
||||
2. 它仍包含具体 panel 事件描述逻辑和面板级状态文案拼装。
|
||||
|
||||
根因:
|
||||
|
||||
- 统一 app event 管线尚未建立。
|
||||
|
||||
收口动作:
|
||||
|
||||
1. 让 `WorkspaceEventSync` 只消费统一 app event。
|
||||
2. 把 panel-specific 事件描述、状态消息格式化下沉到各 feature adapter。
|
||||
3. 将 scene open、selection sync、status update 都纳入正式事件消费流程。
|
||||
|
||||
验收:
|
||||
|
||||
- `WorkspaceEventSync` 不再包含对具体 panel event 结构的硬编码。
|
||||
|
||||
### 九. Scene viewport / gizmo 复杂度仍过高
|
||||
|
||||
问题:
|
||||
|
||||
1. `SceneViewportTransformGizmoSupport.cpp` 仍是超大单体实现。
|
||||
2. gizmo 数学、命中测试、绘制、操作状态、模式逻辑仍高度耦合。
|
||||
|
||||
根因:
|
||||
|
||||
- 旧逻辑迁移后完成了行为闭环,但还没有按稳定子域回收。
|
||||
|
||||
收口动作:
|
||||
|
||||
1. 按 move / rotate / scale 或按 pick / render / manipulate 子域拆分 gizmo 支撑实现。
|
||||
2. 提取共享数学 / 投影 / 命中工具。
|
||||
3. 让 controller 只编排,不直接承担高复杂度细节。
|
||||
|
||||
验收:
|
||||
|
||||
- gizmo 支撑逻辑不再集中在一个超大文件中。
|
||||
- gizmo 模式切换与交互行为更容易定向测试。
|
||||
|
||||
## 执行顺序
|
||||
|
||||
为了避免返工,按以下顺序执行:
|
||||
|
||||
1. 公共接口层去聚合
|
||||
2. 文件粒度与 ownership 标准归一
|
||||
3. Win32 宿主 ownership 收拢
|
||||
4. 平台层反向 UI 依赖切除
|
||||
5. `EditorShellRuntime` 去中心化
|
||||
6. `ProjectPanel` 子域拆分
|
||||
7. feature 统一事件契约
|
||||
8. `WorkspaceEventSync` 正式化
|
||||
9. Scene viewport / gizmo 子域拆分
|
||||
10. 测试与回归收口
|
||||
|
||||
## 验证
|
||||
|
||||
每个阶段至少执行:
|
||||
|
||||
1. `cmake --build build_codex_verify --config Debug --target XCUIEditor editor_ui_smoke_targets`
|
||||
2. `ctest --test-dir build_codex_verify -C Debug -R xcui_editor_app_smoke --output-on-failure`
|
||||
3. `tests/UI/Editor/unit` 的相关定向回归
|
||||
|
||||
必要时补充:
|
||||
|
||||
1. 公共头 include 面回归
|
||||
2. Win32 多窗口 / tab 拖放 / 独立窗口回归
|
||||
3. Scene gizmo 交互回归
|
||||
4. Project tree / grid / rename / context menu / drag-drop 回归
|
||||
|
||||
## 风险控制
|
||||
|
||||
1. 不修改 `managed`、`SRP`、用户其他工作流中的脏改动。
|
||||
2. 任何拆分都必须围绕稳定 ownership,不允许再出现“一两个函数一个 cpp”的假拆分。
|
||||
3. 任何合并都必须基于修改耦合与职责一致性,不做机械回并。
|
||||
4. 若执行中发现某条边界不足以支撑后续步骤,优先补 contract,再迁移实现。
|
||||
@@ -0,0 +1,144 @@
|
||||
# SRP / URP Explicit Scene Setup Policy Plan
|
||||
|
||||
## 背景
|
||||
|
||||
上一阶段已经把 request-level 的一部分策略从 native default 挪到了 managed URP:
|
||||
|
||||
- `Camera.clearMode`
|
||||
- `Camera.stackType`
|
||||
- `CameraRenderRequestContext.clearFlags`
|
||||
- `UniversalRenderPipelineAsset` 中的默认 clear / shadow request policy
|
||||
|
||||
但 `RenderSceneSetup` 这一层还没有真正收口。
|
||||
当前 `UniversalRenderer.ConfigureRenderSceneSetup(...)` 仍然只是调用:
|
||||
|
||||
- `UseDefaultEnvironment()`
|
||||
- `UseDefaultGlobalShaderKeywords()`
|
||||
|
||||
这意味着:
|
||||
|
||||
- URP 还没有显式决定“这帧环境到底是什么”
|
||||
- URP 还没有显式决定“全局 shader keyword 到底开哪些”
|
||||
- native default 仍然在替 URP 做 scene setup policy
|
||||
|
||||
这和目标中的 Unity 风格 `SRP substrate + URP package policy` 不一致。
|
||||
|
||||
## 本阶段目标
|
||||
|
||||
把 scene setup 从“调用 native 默认策略”收成“managed URP 显式配置策略”。
|
||||
|
||||
本阶段只做 seam 收口,不做 deferred,不改 Render Graph 主执行骨架。
|
||||
|
||||
### 目标 1
|
||||
|
||||
扩展 `RenderSceneSetupContext`,让 managed 层拿到显式决策所需的最小上下文:
|
||||
|
||||
- `clearFlags`
|
||||
- `hasMainSceneDepthAttachment`
|
||||
- `hasMainDirectionalShadow`
|
||||
|
||||
### 目标 2
|
||||
|
||||
扩展 managed `Camera` 只读能力,让 URP 可以显式决定 skybox policy:
|
||||
|
||||
- `projectionType`
|
||||
- `skyboxEnabled`
|
||||
- `hasSkyboxMaterial`
|
||||
- `skyboxTopColor`
|
||||
- `skyboxHorizonColor`
|
||||
- `skyboxBottomColor`
|
||||
|
||||
### 目标 3
|
||||
|
||||
扩展 `RenderSceneSetupContext` 的显式写入口:
|
||||
|
||||
- `SetEnvironmentNone()`
|
||||
- `UseCameraSkyboxMaterial()`
|
||||
- `SetProceduralSkybox(...)`
|
||||
- `SetGlobalShaderKeyword(string keyword, bool enabled)`
|
||||
|
||||
### 目标 4
|
||||
|
||||
把 `UniversalRenderer.ConfigureRenderSceneSetup(...)` 改成显式逻辑,复刻当前 native default 行为:
|
||||
|
||||
- 先清空 environment / global keywords
|
||||
- 再根据 camera + request + main scene surface 条件显式设置 skybox
|
||||
- 再根据 `hasMainDirectionalShadow` 显式设置 `XC_MAIN_LIGHT_SHADOWS`
|
||||
|
||||
## 实施步骤
|
||||
|
||||
### Step 1. 补齐 managed / native scene setup bridge
|
||||
|
||||
在 `RenderSceneSetupContext` 与 `MonoScriptRuntime` 之间增加新的只读属性和显式写接口。
|
||||
|
||||
要求:
|
||||
|
||||
- 不引入兼容层
|
||||
- 不保留“旧 API + 新 API 并存但无人使用”的半弃用状态
|
||||
- scene setup 的显式接口命名要直接表达意图
|
||||
|
||||
### Step 2. 补齐 Camera 的只读 skybox / projection seam
|
||||
|
||||
通过 internal call 暴露 managed 决策所需的 camera 状态。
|
||||
|
||||
要求:
|
||||
|
||||
- 只补当前 scene setup 确实需要的读取能力
|
||||
- 不顺手扩一堆暂时无用的 Camera API
|
||||
|
||||
### Step 3. 切换 UniversalRenderer 的 scene setup 实现
|
||||
|
||||
把当前两句 `UseDefault...` 换成显式策略代码。
|
||||
|
||||
要求:
|
||||
|
||||
- 行为尽量与当前默认行为一致
|
||||
- 不再依赖 native default 来决定 keyword / environment
|
||||
- feature 后续仍可以在 `ConfigureRenderSceneSetup(...)` 链路里继续覆写
|
||||
|
||||
## 收口标准
|
||||
|
||||
- `UniversalRenderer.ConfigureRenderSceneSetup(...)` 不再调用 native default environment / keyword policy
|
||||
- URP 可以显式配置:
|
||||
- environment none
|
||||
- camera material skybox
|
||||
- procedural skybox
|
||||
- global shader keyword on/off
|
||||
- `XC_MAIN_LIGHT_SHADOWS` 由 managed scene setup 显式决定
|
||||
- `XCEditor` Debug 编译通过
|
||||
- 旧版 editor 冒烟通过
|
||||
|
||||
## 非目标
|
||||
|
||||
本阶段不做以下内容:
|
||||
|
||||
- deferred rendering
|
||||
- shadow 算法本体迁移
|
||||
- gaussian / volumetric pass 迁移
|
||||
- Render Graph 结构大改
|
||||
- editor / new_editor 相关重构
|
||||
|
||||
## 完成情况
|
||||
|
||||
- 已补齐 managed `Camera` 的 scene setup 只读 seam:
|
||||
- `projectionType`
|
||||
- `skyboxEnabled`
|
||||
- `hasSkyboxMaterial`
|
||||
- `skyboxTopColor`
|
||||
- `skyboxHorizonColor`
|
||||
- `skyboxBottomColor`
|
||||
- 已补齐 `RenderSceneSetupContext` 的显式 scene setup seam:
|
||||
- `clearFlags`
|
||||
- `hasMainSceneDepthAttachment`
|
||||
- `hasMainDirectionalShadow`
|
||||
- `SetEnvironmentNone()`
|
||||
- `UseCameraSkyboxMaterial()`
|
||||
- `SetProceduralSkybox(...)`
|
||||
- `SetGlobalShaderKeyword(string, bool)`
|
||||
- 已删除不再使用的 managed scene setup default / 清空兼容 API,避免双轨状态继续存在
|
||||
- `UniversalRenderer.ConfigureRenderSceneSetup(...)` 已切换为显式策略:
|
||||
- 显式决定 skybox environment 是否启用
|
||||
- 显式决定材质天空盒 / procedural skybox
|
||||
- 显式决定 `XC_MAIN_LIGHT_SHADOWS`
|
||||
- `XCEditor` Debug 编译通过
|
||||
- 旧版 editor 冒烟通过
|
||||
@@ -0,0 +1,68 @@
|
||||
# SRP / URP Feature Runtime Controller Split Plan
|
||||
|
||||
时间:2026-04-22
|
||||
|
||||
## 背景
|
||||
|
||||
当前 renderer block 和 feature injection 骨架已经基本成形,但 feature 层还有最后一块不够整齐:
|
||||
|
||||
1. `BuiltinGaussianSplatRendererFeature` / `BuiltinVolumetricRendererFeature` 已经走了 runtime controller 模式。
|
||||
2. `ColorScalePostProcessRendererFeature` 仍然直接持有 runtime pass,并且 pass 反向引用 feature。
|
||||
3. `RenderObjectsRendererFeature` 也仍然把配置解析、runtime pass 构建、enqueue 逻辑都混在 feature 里。
|
||||
|
||||
这导致 feature 层的边界还不统一:
|
||||
|
||||
- 有的 feature 是“配置数据 + controller”
|
||||
- 有的 feature 还是“配置数据 + runtime pass 直接混写”
|
||||
|
||||
## 本阶段目标
|
||||
|
||||
把 `ColorScalePostProcessRendererFeature` 和 `RenderObjectsRendererFeature` 也收成统一的“配置数据 + runtime controller”模式。
|
||||
|
||||
目标结果:
|
||||
|
||||
1. `ColorScalePostProcessPass` 不再反向持有 feature 资产引用。
|
||||
2. `RenderObjectsRendererFeature` 的配置解析与 runtime pass 持有分离。
|
||||
3. 当前内建 feature 的 runtime 边界风格统一。
|
||||
|
||||
## 范围
|
||||
|
||||
本阶段只处理 feature runtime 边界,不做:
|
||||
|
||||
- public renderer feature API 改造
|
||||
- deferred rendering
|
||||
- C++ host / RenderGraph 改造
|
||||
|
||||
## 实施步骤
|
||||
|
||||
### 1. 拆出 feature settings / controller
|
||||
|
||||
新增:
|
||||
|
||||
- `ColorScalePostProcessSettings`
|
||||
- `UniversalColorScalePostProcessController`
|
||||
- `RenderObjectsFeatureSettings`
|
||||
- `UniversalRenderObjectsFeatureController`
|
||||
|
||||
### 2. 接入现有 feature
|
||||
|
||||
接入:
|
||||
|
||||
- `ColorScalePostProcessRendererFeature`
|
||||
- `RenderObjectsRendererFeature`
|
||||
|
||||
### 3. 验证
|
||||
|
||||
要求:
|
||||
|
||||
1. `XCEditor` Debug 构建通过
|
||||
2. old editor 冒烟至少 10 秒
|
||||
3. `editor.log` 出现 `SceneReady`
|
||||
|
||||
## 完成标准
|
||||
|
||||
满足以下条件才算本阶段收口:
|
||||
|
||||
1. `ColorScale` 与 `RenderObjects` 都改成配置数据 + runtime controller。
|
||||
2. 不再存在 runtime pass 直接反向持有 feature 资产的耦合。
|
||||
3. `XCEditor` 编译与 old editor 冒烟通过。
|
||||
@@ -0,0 +1,73 @@
|
||||
# SRP / URP Main Scene Feature Injection Plan
|
||||
|
||||
时间:2026-04-22
|
||||
|
||||
## 背景
|
||||
|
||||
当前 renderer block 主线已经基本清晰:
|
||||
|
||||
- `ShadowCaster`
|
||||
- `DepthPrepass`
|
||||
- `MainScene`
|
||||
- `PostProcess`
|
||||
- `FinalOutput`
|
||||
|
||||
`UniversalRenderer` 也已经拆出了对应 block owner。
|
||||
|
||||
但 `main scene` 这一面的 renderer feature 注入还不够干净:
|
||||
|
||||
1. `RenderObjectsRendererFeature` 自己手写 scene-stage 与 pass-stage 判断。
|
||||
2. `BuiltinGaussianSplatRendererFeature` / `BuiltinVolumetricRendererFeature` 各自重复一套 native scene feature pass 注入逻辑。
|
||||
3. 缺少统一的 main-scene feature 注入骨架,后续继续加 scene feature 时还会复制这些判断和样板。
|
||||
|
||||
## 本阶段目标
|
||||
|
||||
补齐 `main scene` feature 注入的统一 utility / controller,把当前散落在 feature 里的 main-scene 注入规则收口。
|
||||
|
||||
目标结果:
|
||||
|
||||
1. `RenderObjectsRendererFeature` 走统一的 main-scene pass 注入 helper。
|
||||
2. Gaussian / Volumetric 共用同一套 native scene feature controller。
|
||||
3. 后续再加 main-scene renderer feature 时,有稳定的落点可复用。
|
||||
|
||||
## 范围
|
||||
|
||||
本阶段只处理 main-scene feature 注入骨架,不做:
|
||||
|
||||
- public renderer feature API 改造
|
||||
- deferred rendering
|
||||
- C++ host / RenderGraph 改造
|
||||
|
||||
## 实施步骤
|
||||
|
||||
### 1. 新增 main-scene feature 注入 utility
|
||||
|
||||
职责:
|
||||
|
||||
- 统一判断当前是否处于 main scene stage
|
||||
- 统一判断 pass 是否属于当前 stage
|
||||
- 统一执行 enqueue
|
||||
|
||||
### 2. 新增 native scene feature controller
|
||||
|
||||
职责:
|
||||
|
||||
- 持有 `NativeSceneFeaturePass`
|
||||
- 统一 create / configure / enqueue
|
||||
- 供 Gaussian / Volumetric 复用
|
||||
|
||||
### 3. 接入现有 feature
|
||||
|
||||
接入:
|
||||
|
||||
- `RenderObjectsRendererFeature`
|
||||
- `BuiltinGaussianSplatRendererFeature`
|
||||
- `BuiltinVolumetricRendererFeature`
|
||||
|
||||
## 完成标准
|
||||
|
||||
满足以下条件才算本阶段收口:
|
||||
|
||||
1. main-scene feature 注入规则不再散落在多个 feature 里重复实现。
|
||||
2. Gaussian / Volumetric 共用统一 native scene feature controller。
|
||||
3. `XCEditor` 编译通过,old editor 冒烟通过。
|
||||
@@ -0,0 +1,63 @@
|
||||
# SRP / URP Managed Final Color Request Policy Plan
|
||||
|
||||
## Background
|
||||
|
||||
The previous SRP cleanup already moved several policies out of native defaults and into managed URP request/planning seams.
|
||||
The remaining native baseline dependency was `final color policy`:
|
||||
|
||||
- pipeline default final color settings
|
||||
- camera final color overrides
|
||||
- `requiresProcessing` source data
|
||||
|
||||
That policy was still injected from native camera-frame baseline into `CameraFramePlan.finalColorPolicy`, which meant renderer-backed URP was not yet the real owner of final color policy.
|
||||
|
||||
## Goal
|
||||
|
||||
Move final color policy ownership from native camera-frame baseline into the managed request seam.
|
||||
|
||||
After this phase:
|
||||
|
||||
- URP resolves final color policy in `ConfigureRendererCameraRequest(...)`
|
||||
- `CameraRenderRequest.finalColorPolicy` becomes the source of truth
|
||||
- `CameraFramePlan` simply inherits the resolved request policy
|
||||
- the native `UsesNativeCameraFramePlanBaseline*` bridge is removed
|
||||
|
||||
## Design
|
||||
|
||||
### 1. Camera read seam
|
||||
|
||||
Expose managed read access for camera final color overrides:
|
||||
|
||||
- `Camera.hasFinalColorOverrides`
|
||||
- `Camera.GetFinalColorOverrideSettings()`
|
||||
|
||||
### 2. Request write seam
|
||||
|
||||
Expose managed write access for resolved request policy:
|
||||
|
||||
- `CameraRenderRequestContext.SetResolvedFinalColorPolicy(...)`
|
||||
- `CameraRenderRequestContext.ClearFinalColorPolicy()`
|
||||
|
||||
### 3. URP policy ownership
|
||||
|
||||
`UniversalRenderPipelineAsset.ConfigureRendererCameraRequest(...)` should:
|
||||
|
||||
- read pipeline default final color settings
|
||||
- read camera overrides
|
||||
- resolve the final settings
|
||||
- write the resolved policy back into request context
|
||||
|
||||
## Completion
|
||||
|
||||
- Status: completed on 2026-04-21
|
||||
- Added managed `FinalColorOverrideSettings`
|
||||
- Added camera final color override read seam
|
||||
- Added request-context final color policy write seam
|
||||
- Moved URP final color resolution into managed request configuration
|
||||
- Removed `UsesNativeCameraFramePlanBaseline*` from managed/native SRP bridge
|
||||
|
||||
## Verification
|
||||
|
||||
- `cmake --build . --config Debug --target XCEditor`
|
||||
- old editor smoke passed
|
||||
- `SceneReady elapsed_ms=6129 first_frame_ms=719`
|
||||
@@ -0,0 +1,107 @@
|
||||
# SRP / URP Managed Fullscreen Auxiliary Texture Binding Plan
|
||||
|
||||
时间:2026-04-22
|
||||
|
||||
## 背景
|
||||
|
||||
上一阶段已经补上了 managed raster pass 对 depth 读依赖和 depth attachment 的声明能力,但这条链只走到了 render graph 依赖记录层,并没有真正把额外输入纹理绑定到 fullscreen/custom pass 的 shader 资源槽位。
|
||||
|
||||
当前实际问题:
|
||||
|
||||
1. `RenderGraphRasterPassBuilder.UseTexture(...)` / `UseDepthTexture(...)` 只声明读依赖,不会形成 shader 资源绑定。
|
||||
2. `BuiltinVectorFullscreenPass` 仍然是手写单 `SourceColorTexture` + 单 sampler 的 descriptor layout。
|
||||
3. render graph callback 在执行 `RenderPassContext` 时只携带 `sourceColorView`,没有携带额外输入纹理的 SRV。
|
||||
4. render graph 对 transient depth 只建了 DSV,没有建可采样的 SRV,导致 graph 内部深度纹理即使声明为 read depth,也不能被 fullscreen shader 真正采样。
|
||||
|
||||
这会导致 managed SRP / URP 侧写出来的 fullscreen/custom pass 只能做“单输入 source color”效果,无法形成真正可用的自定义后处理输入面。
|
||||
|
||||
## 本阶段目标
|
||||
|
||||
把 managed fullscreen/custom pass 的“声明输入纹理”与“运行时真实绑定纹理”收成闭环,并保持架构方向继续对齐 Unity 风格:
|
||||
|
||||
- C++ core 继续拥有 render graph、资源生命周期和执行调度。
|
||||
- managed SRP / URP 继续拥有 pass authoring 和 shader 输入声明。
|
||||
- fullscreen pass 不再手写固定单纹理布局,而是接到现有 shader 资源绑定计划能力上。
|
||||
|
||||
## 范围
|
||||
|
||||
本阶段只做 fullscreen/custom raster pass 输入绑定闭环,不做:
|
||||
|
||||
- deferred pipeline
|
||||
- shadow 系统迁移
|
||||
- surface/imported texture 多视图系统大改
|
||||
- renderer 多实现切换
|
||||
|
||||
## 实施步骤
|
||||
|
||||
### 1. Managed API 补齐“按 shader 资源名绑定输入纹理”
|
||||
|
||||
在 `RenderGraphRasterPassBuilder` 增加显式输入绑定 API:
|
||||
|
||||
- `BindTexture(string shaderResourceName, RenderGraphTextureHandle texture)`
|
||||
- `BindDepthTexture(string shaderResourceName, RenderGraphTextureHandle texture)`
|
||||
|
||||
这两个 API 需要同时完成两件事:
|
||||
|
||||
1. 自动登记 graph read dependency
|
||||
2. 自动登记 runtime shader resource binding request
|
||||
|
||||
这样 managed 侧不会再出现“声明读了,但执行没绑上”的双轨状态。
|
||||
|
||||
### 2. Mono bridge 保留纹理绑定描述
|
||||
|
||||
在 `ManagedScriptableRenderContextState::RasterPassRecordRequest` 中新增 fullscreen 输入绑定记录,至少包含:
|
||||
|
||||
- shader resource name
|
||||
- render graph texture handle
|
||||
- texture aspect(color / depth)
|
||||
|
||||
并增加 internal call,把 managed builder 的输入绑定请求带到 native。
|
||||
|
||||
### 3. RenderGraph callback 执行上下文补额外 SRV
|
||||
|
||||
扩展 `RenderPassContext`,让 callback/fullscreen pass 在执行时能拿到:
|
||||
|
||||
- `sourceColorView`
|
||||
- 额外输入纹理对应的已解析 SRV 列表
|
||||
|
||||
执行阶段需要按 handle 解析实际 view:
|
||||
|
||||
- `sourceColorTexture` 特殊走现有 `sourceColorView`
|
||||
- 其他 graph-managed 纹理走 `ResolveTextureView(..., ShaderResource)`
|
||||
- 如果拿不到 shader-readable view,则 pass 执行失败
|
||||
|
||||
### 4. 补 transient depth SRV
|
||||
|
||||
render graph runtime 目前对 transient depth 只创建 DSV,不创建 SRV。
|
||||
|
||||
需要修改 runtime texture allocation 逻辑,让 transient depth 也能生成 `shaderResourceView`,从而支持 fullscreen shader 读取 graph 内部 depth texture。
|
||||
|
||||
### 5. BuiltinVectorFullscreenPass 接入 shader 资源绑定计划
|
||||
|
||||
把 `BuiltinVectorFullscreenPass` 从“手写 3 个 descriptor set”改成:
|
||||
|
||||
- 解析 shader pass 的资源绑定计划
|
||||
- 基于 binding plan 自动创建 set layout / pipeline layout
|
||||
- 自动填充 `PassConstants`
|
||||
- 自动填充 `SourceColorTexture`
|
||||
- 自动填充 `LinearClampSampler`
|
||||
- 对其余 `Texture2D` 资源按 resource name 从 runtime 输入绑定表里解析
|
||||
|
||||
也就是说,fullscreen vector pass 要变成一个真正的“受控小型 material/fullscreen pass”,而不是只支持 `SourceColorTexture` 的专用壳。
|
||||
|
||||
## 阶段完成标准
|
||||
|
||||
满足以下条件才算本阶段收口:
|
||||
|
||||
1. managed fullscreen/custom pass 可以声明并真正绑定额外 color/depth 输入纹理。
|
||||
2. `BuiltinVectorFullscreenPass` 不再硬编码单纹理 descriptor layout。
|
||||
3. graph 内部 transient depth 能生成并提供可采样 SRV。
|
||||
4. `XCEditor` Debug 构建通过。
|
||||
5. old editor 冒烟至少 10-15 秒通过,日志出现 `SceneReady`。
|
||||
|
||||
## 已知边界
|
||||
|
||||
本阶段不主动扩 surface/imported texture 的多视图系统。
|
||||
|
||||
也就是说,若某些 imported texture 当前只有 RTV / DSV、没有独立 SRV 视图,这部分仍然不是完整方案;后续如果要让任意 imported color/depth 都可被 graph 中任意 pass 采样,需要单独做 imported resource multi-view / surface-view ownership 收口计划。
|
||||
@@ -0,0 +1,107 @@
|
||||
# SRP / URP Managed Render Graph Fullscreen Depth Surface Plan
|
||||
|
||||
Date: 2026-04-21
|
||||
|
||||
## Background
|
||||
|
||||
The current SRP / URP managed render-graph surface is usable, but still too
|
||||
thin in one important place:
|
||||
|
||||
- managed fullscreen raster passes can read source color
|
||||
- managed fullscreen raster passes can write color targets
|
||||
- managed fullscreen raster passes cannot explicitly declare depth-texture reads
|
||||
- managed fullscreen raster passes cannot explicitly keep or override a depth
|
||||
attachment
|
||||
|
||||
That is an architectural gap, not just a convenience issue.
|
||||
|
||||
If a C# renderer feature wants to implement a depth-aware fullscreen effect
|
||||
(for example edge detection, fog composition, SSAO-style composition, depth
|
||||
conditioned blur, or custom outline logic), it currently has no correct managed
|
||||
API surface to describe that dependency to the native render graph.
|
||||
|
||||
So even though the native render graph already supports depth texture access,
|
||||
the managed SRP surface still under-expresses the dependency graph.
|
||||
|
||||
## Goal
|
||||
|
||||
Close the first managed render-graph execution-surface gap by making managed
|
||||
fullscreen raster recording depth-aware.
|
||||
|
||||
After this stage:
|
||||
|
||||
- managed C# fullscreen raster passes can declare depth texture reads
|
||||
- managed C# fullscreen raster passes can explicitly set a depth attachment when
|
||||
needed
|
||||
- the Mono bridge preserves those declarations into the native render graph
|
||||
- native graph recording uses depth-as-depth semantics instead of treating every
|
||||
read texture as color
|
||||
|
||||
## Scope
|
||||
|
||||
Included:
|
||||
|
||||
- `managed/XCEngine.ScriptCore/Rendering/Core/ScriptableRenderContext.cs`
|
||||
- `managed/XCEngine.ScriptCore/Rendering/Graph/RenderGraphRasterPassBuilder.cs`
|
||||
- `managed/XCEngine.ScriptCore/InternalCalls.cs`
|
||||
- `engine/src/Scripting/Mono/MonoScriptRuntime.cpp`
|
||||
- `engine/include/XCEngine/Rendering/RenderPassGraphContract.h`
|
||||
- `engine/src/Rendering/RenderPassGraphContract.cpp`
|
||||
|
||||
Not included:
|
||||
|
||||
- deferred renderer work
|
||||
- moving shadow / gaussian / volumetric runtime ownership in this phase
|
||||
- generic managed compute-pass authoring in this phase
|
||||
- editor / new_editor work
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
1. Extend managed raster-pass builder with depth read / depth attachment APIs
|
||||
2. Extend Mono internal calls and pending managed fullscreen-pass request state
|
||||
3. Preserve depth reads separately from color reads through native bridge flush
|
||||
4. Teach native raster-pass graph recording to issue depth reads with correct
|
||||
render-graph aspect semantics
|
||||
5. Rebuild old `XCEditor`
|
||||
6. Run old editor smoke for at least 10 seconds and verify `SceneReady`
|
||||
7. Archive the plan, commit, and push
|
||||
|
||||
## Exit Criteria
|
||||
|
||||
- managed code can call APIs equivalent to:
|
||||
- `UseDepthTexture(...)`
|
||||
- `SetDepthAttachment(...)`
|
||||
- native bridge stores depth reads independently from color reads
|
||||
- native render-graph recording emits `ReadDepthTexture(...)` for managed depth
|
||||
inputs
|
||||
- old `XCEditor` Debug build succeeds
|
||||
- old editor smoke succeeds
|
||||
|
||||
## Why This Stage First
|
||||
|
||||
This is the right next step because it improves the managed SRP execution
|
||||
surface without prematurely expanding into deferred rendering or feature
|
||||
migration.
|
||||
|
||||
It makes the current managed URP layer materially more useful for real custom
|
||||
renderer features, while keeping the change scoped and architecture-driven.
|
||||
|
||||
## Result
|
||||
|
||||
Completed on 2026-04-21.
|
||||
|
||||
- extended managed fullscreen raster-pass authoring with:
|
||||
- `UseDepthTexture(...)`
|
||||
- `SetDepthAttachment(...)`
|
||||
- extended Mono internal-call bridge to preserve fullscreen managed depth reads
|
||||
and optional depth attachment overrides
|
||||
- extended native raster-pass graph recording to emit depth reads with
|
||||
`ReadDepthTexture(...)` instead of treating all managed read dependencies as
|
||||
color
|
||||
- preserved existing fullscreen source-color path and final-output behavior
|
||||
|
||||
## Verification
|
||||
|
||||
- `cmake --build . --config Debug --target XCEditor`
|
||||
- old editor smoke passed
|
||||
- `SceneReady elapsed_ms=5621 first_frame_ms=602`
|
||||
@@ -0,0 +1,74 @@
|
||||
# SRP / URP Native Scene Feature Id Bridge Plan
|
||||
|
||||
## Background
|
||||
|
||||
Current managed URP feature wrappers for gaussian splat and volumetric rendering
|
||||
already live in the URP package, but the bridge into native runtime still uses
|
||||
string names:
|
||||
|
||||
- managed `NativeSceneFeaturePass("BuiltinGaussianSplatPass", ...)`
|
||||
- managed `NativeSceneFeaturePass("BuiltinVolumetricPass", ...)`
|
||||
- native host resolves feature passes by string comparison
|
||||
|
||||
This is a transitional seam, not a stable long-term SRP/URP backbone.
|
||||
|
||||
## Goal
|
||||
|
||||
Replace string-based native scene feature dispatch with an explicit feature id bridge.
|
||||
|
||||
After this phase:
|
||||
|
||||
- managed URP records native scene features by enum/id
|
||||
- native scene feature host resolves by stable feature id
|
||||
- feature pass names remain only for logging / graph labeling
|
||||
- future native-backed URP features can reuse the same bridge cleanly
|
||||
|
||||
## Scope
|
||||
|
||||
### Step 1. Add explicit native scene feature id type
|
||||
|
||||
- add native enum for scene feature ids
|
||||
- add managed enum mirror
|
||||
- keep values explicit and stable
|
||||
|
||||
### Step 2. Move recorder bridge from string to id
|
||||
|
||||
- `ScriptableRenderContext.RecordNativeSceneFeaturePass(...)`
|
||||
- Mono internal call bridge
|
||||
- `NativeSceneRecorder::RecordFeaturePass(...)`
|
||||
- `SceneRenderFeatureHost::RecordFeaturePass(...)`
|
||||
|
||||
### Step 3. Bind builtin native features to explicit ids
|
||||
|
||||
- `BuiltinGaussianSplatPass`
|
||||
- `BuiltinVolumetricPass`
|
||||
- managed `NativeSceneFeaturePass`
|
||||
- managed builtin renderer features
|
||||
|
||||
## Non-goals
|
||||
|
||||
- changing gaussian splat runtime logic
|
||||
- changing volumetric runtime logic
|
||||
- moving shadow runtime in this phase
|
||||
- deferred renderer work
|
||||
|
||||
## Exit Criteria
|
||||
|
||||
- no managed/native string-based native feature dispatch remains
|
||||
- old editor `XCEditor` Debug build passes
|
||||
- old editor smoke reaches `SceneReady`
|
||||
|
||||
## Result
|
||||
|
||||
Completed on 2026-04-21.
|
||||
|
||||
- added explicit native/managed `NativeSceneFeaturePassId` enums
|
||||
- replaced string-based native scene feature pass recording with id-based dispatch
|
||||
- bound builtin gaussian splat / volumetric native passes to stable ids
|
||||
- kept pass names only for logging and render-graph labeling
|
||||
|
||||
## Verification
|
||||
|
||||
- `cmake --build . --config Debug --target XCEditor`
|
||||
- old editor smoke passed
|
||||
- `SceneReady elapsed_ms=6277 first_frame_ms=637`
|
||||
@@ -0,0 +1,86 @@
|
||||
# SRP / URP Native Scene Feature Registration Ownership Plan
|
||||
|
||||
## Background
|
||||
|
||||
Current native gaussian splat / volumetric scene feature passes have already
|
||||
been lifted into a managed URP-facing wrapper layer:
|
||||
|
||||
- `UniversalRendererData` owns the default feature list
|
||||
- managed URP records native scene features explicitly
|
||||
- native dispatch now uses stable `NativeSceneFeaturePassId`
|
||||
|
||||
But one C++ ownership seam is still dirty:
|
||||
|
||||
- `BuiltinForwardPipeline` constructor silently registers default native scene
|
||||
feature passes
|
||||
- that means pipeline instantiation itself still decides which first-party
|
||||
native scene features exist
|
||||
- the default backend asset / scene draw backend factory do not own that policy
|
||||
|
||||
This keeps an avoidable hidden side effect inside the pipeline runtime object.
|
||||
|
||||
## Goal
|
||||
|
||||
Move default native scene feature registration out of
|
||||
`BuiltinForwardPipeline` construction and into explicit backend
|
||||
configuration/factory ownership.
|
||||
|
||||
After this phase:
|
||||
|
||||
- `BuiltinForwardPipeline` only owns execution/runtime state
|
||||
- default native scene feature availability is configured by
|
||||
backend asset/factory code
|
||||
- default backend asset creation and default scene draw backend creation share
|
||||
the same setup path
|
||||
|
||||
## Scope
|
||||
|
||||
### Step 1. Remove constructor-side feature registration
|
||||
|
||||
- stop registering default scene features inside
|
||||
`BuiltinForwardPipeline::BuiltinForwardPipeline()`
|
||||
|
||||
### Step 2. Centralize configured builtin forward creation
|
||||
|
||||
- introduce one explicit setup path for default builtin forward scene features
|
||||
- use that path from `BuiltinForwardPipelineAsset`
|
||||
- use that path from default scene draw backend creation / fallback creation
|
||||
|
||||
### Step 3. Verify no behavior regression
|
||||
|
||||
- rebuild old `XCEditor`
|
||||
- run old editor smoke until `SceneReady`
|
||||
|
||||
## Non-goals
|
||||
|
||||
- changing gaussian splat runtime logic
|
||||
- changing volumetric runtime logic
|
||||
- moving shadow runtime in this phase
|
||||
- deferred renderer work
|
||||
- editor / new_editor work
|
||||
|
||||
## Exit Criteria
|
||||
|
||||
- `BuiltinForwardPipeline` constructor no longer performs implicit native scene
|
||||
feature registration
|
||||
- default builtin forward backend creation still exposes gaussian splat /
|
||||
volumetric native features through the explicit factory path
|
||||
- old editor `XCEditor` Debug build passes
|
||||
- old editor smoke reaches `SceneReady`
|
||||
|
||||
## Result
|
||||
|
||||
Completed on 2026-04-21.
|
||||
|
||||
- removed constructor-side default native scene feature registration from
|
||||
`BuiltinForwardPipeline`
|
||||
- centralized configured builtin forward creation in
|
||||
`BuiltinForwardSceneSetup`
|
||||
- routed builtin forward asset creation, default scene draw backend creation,
|
||||
and host fallback creation through the same configured pipeline path
|
||||
|
||||
## Verification
|
||||
|
||||
- `cmake --build . --config Debug --target XCEditor`
|
||||
- old editor smoke passed
|
||||
- `SceneReady elapsed_ms=5493 first_frame_ms=614`
|
||||
@@ -0,0 +1,40 @@
|
||||
# SRP/URP ObjectId Tooling Boundary Plan
|
||||
|
||||
日期:2026-04-21
|
||||
|
||||
## 背景
|
||||
|
||||
`ObjectId` 这条链路当前主要用于 editor 视口拾取和选中描边,不属于 runtime SRP/URP 主渲染能力。
|
||||
|
||||
上一阶段把 standalone stage fallback ownership 从 host 往 backend 收口时,`ObjectId` 也一起落到了 builtin forward backend setup 中。这个方向不对:
|
||||
|
||||
1. `ShadowCaster` / `DepthOnly` 属于 scene rendering stage,适合归到 backend 或 renderer 规划边界。
|
||||
2. `ObjectId` 更像 tooling render request,只在 editor / picking / selection 这条链路上使用。
|
||||
3. 如果把 `ObjectId` 继续和 shadow/depth 混在一起,会误导后续 SRP/URP 分层,让它看起来像 URP runtime feature。
|
||||
|
||||
## 目标
|
||||
|
||||
1. 把 `ObjectId` 从 builtin forward backend ownership 中移出。
|
||||
2. 把 `ObjectId` 重新挂到顶层 `CameraRenderer` 执行入口,作为通用 tooling pass 能力。
|
||||
3. 保持 editor 视口 object-id picking 行为不变。
|
||||
|
||||
## 实施步骤
|
||||
|
||||
1. 从 `BuiltinForwardSceneSetup` 中移除 `BuiltinObjectIdPass` 注册。
|
||||
2. 在 `CameraRenderer` 顶层 pipeline 绑定路径中补上 object-id tooling pass 注入。
|
||||
3. 重新编译旧版 `XCEditor`,运行旧版 editor 冒烟并确认 `SceneReady`。
|
||||
|
||||
## 完成判定
|
||||
|
||||
1. builtin forward backend 不再拥有 `ObjectId` fallback 注册。
|
||||
2. `CameraRenderer` 创建或切换顶层 pipeline 后,会显式提供 `ObjectId` tooling pass。
|
||||
3. 旧版 editor 编译通过并冒烟通过。
|
||||
|
||||
## 结果
|
||||
|
||||
1. `BuiltinForwardSceneSetup` 已移除 `BuiltinObjectIdPass` 注册,builtin forward backend 现在只保留 scene-stage 相关 fallback。
|
||||
2. `CameraRenderer` 在顶层 pipeline 绑定路径中统一注入 `ObjectId` standalone pass,语义上归为 tooling/editor request。
|
||||
3. 验证结果:
|
||||
`cmake --build . --config Debug --target XCEditor` 通过。
|
||||
旧版 editor 冒烟 15 秒通过。
|
||||
日志结果:`SceneReady elapsed_ms=5621 first_frame_ms=602`。
|
||||
@@ -0,0 +1,28 @@
|
||||
# SRP/URP Probe ScriptableObject Authoring Cleanup Plan
|
||||
|
||||
日期:2026-04-21
|
||||
|
||||
## 背景
|
||||
|
||||
当前生产代码里的 `RenderPipelineAsset`、`ScriptableRendererData`、`ScriptableRendererFeature` 已经切到 `ScriptableObject` 基底,并且默认创建路径开始优先走 `ScriptableObject.CreateInstance(...)`。
|
||||
|
||||
但 `managed/GameScripts/RenderPipelineApiProbe.cs` 里仍然残留一批直接 `new` 出 render asset、renderer data、renderer feature 的路径。这会让 probe 的 authoring 语义落后于当前 SRP/URP 主线,也会让后续继续按 Unity 风格推进时,测试/探针层和产品层出现分叉。
|
||||
|
||||
## 目标
|
||||
|
||||
1. 把 probe 中由脚本直接 author 的 render asset / renderer data / renderer feature 创建路径统一到 `ScriptableObject.CreateInstance(...)`。
|
||||
2. 对少数仍依赖带参构造的 probe `ScriptableObject` 子类,改成 Unity 风格的“无参创建 + 字段配置”。
|
||||
3. 不改 native backend,不改 `new_editor`,只收口 probe authoring 语义。
|
||||
|
||||
## 实施步骤
|
||||
|
||||
1. 在 `RenderPipelineApiProbe.cs` 中补一个轻量的 ScriptableObject probe 工具,统一创建和空值过滤。
|
||||
2. 迁移 probe asset 构造、runtime selection probe、renderer data 默认 feature 配置,移除直接 `new` 出 `ScriptableObject` 派生类型的路径。
|
||||
3. 处理少数带参构造的 probe feature / renderer data,使其可通过 `CreateInstance(...)` 创建后再配置。
|
||||
4. 重新编译 `XCEditor`,运行旧版 `editor/bin/Debug/XCEngine.exe` 冒烟至少 10 秒,确认 `SceneReady`。
|
||||
|
||||
## 完成判定
|
||||
|
||||
1. `RenderPipelineApiProbe.cs` 中 probe authoring 路径不再直接 `new` 出 render asset / renderer data / renderer feature。
|
||||
2. `cmake --build build --config Debug --target XCEditor` 成功。
|
||||
3. 旧版 editor 冒烟通过,日志出现新的 `SceneReady`。
|
||||
@@ -0,0 +1,93 @@
|
||||
# SRP / URP Render Graph Imported Surface Multi-View Plan
|
||||
|
||||
时间:2026-04-22
|
||||
|
||||
## 背景
|
||||
|
||||
上一阶段已经打通了 managed fullscreen/custom pass 的额外纹理绑定链路,也补上了 transient depth 的 SRV 创建。
|
||||
|
||||
但 render graph 对 imported texture 的建模仍然是不完整的:
|
||||
|
||||
1. `RenderGraph::TextureResource` 只保存了一个 `importedView`
|
||||
2. `RenderGraphRuntimeResources::ResolveTextureView(...)` 对 imported texture 不区分请求的 view type,直接返回这一份 view
|
||||
3. imported color / depth 一旦进入 graph,就无法稳定地在不同阶段之间切换 `RTV / DSV / SRV`
|
||||
4. graph-managed imported surface 在 fullscreen/custom pass 中采样 imported depth / color 时,仍然可能拿到错误类型的 view
|
||||
|
||||
这会导致 render graph 表面上已经接管 imported surface 的生命周期与状态调度,但在真正执行时还没有形成“纹理资源 + 多视图解析”的闭环。
|
||||
|
||||
## 本阶段目标
|
||||
|
||||
把 imported texture 从“只有一个盲视图指针”升级成“保留底层纹理资源,并能按需解析不同 view type”的运行时模型。
|
||||
|
||||
阶段完成后应满足:
|
||||
|
||||
1. imported texture 能从 `RHIResourceView` 反查到底层 `RHITexture`
|
||||
2. render graph 能为 imported texture 按请求解析 `RenderTarget / DepthStencil / ShaderResource / UnorderedAccess`
|
||||
3. 对 graph-owned imported transitions,不再依赖导入时碰巧传进来的那一个 view 类型
|
||||
4. managed fullscreen/custom pass 采样 imported surface 时,color / depth 都能走统一的 `ResolveTextureView(..., ShaderResource)` 路径
|
||||
5. `XCEditor` Debug 构建通过,old editor 冒烟至少 10-15 秒并出现 `SceneReady`
|
||||
|
||||
## 范围
|
||||
|
||||
本阶段只收口 imported texture multi-view 运行时能力,不做:
|
||||
|
||||
- deferred pipeline
|
||||
- shadow 系统迁移
|
||||
- editor 侧功能扩展
|
||||
- imported buffer multi-view 建模
|
||||
- RenderSurface 大规模重做
|
||||
|
||||
## 实施步骤
|
||||
|
||||
### 1. 抬升 texture-backed view 抽象
|
||||
|
||||
在 `RHIResourceView` 抽象层增加统一接口,让上层可以判断一个 view 是否绑定到某个 `RHITexture`。
|
||||
|
||||
要求:
|
||||
|
||||
- `RHIResourceView` 暴露 `GetTextureResource()`
|
||||
- Vulkan / OpenGL 返回各自已经持有的 texture 指针
|
||||
- D3D12 纹理视图补齐 `D3D12Texture*` 存储,并通过该接口返回
|
||||
- buffer view 继续返回空指针
|
||||
|
||||
### 2. 扩展 render graph imported texture 元数据
|
||||
|
||||
在 render graph builder / compiler / runtime 之间,把 imported texture 的“底层纹理资源”一起传下去,而不是只传一份 primary view。
|
||||
|
||||
要求:
|
||||
|
||||
- `RenderGraph::TextureResource` 记录 imported texture 指针
|
||||
- `CompiledRenderGraph::CompiledTexture` 同步保存该信息
|
||||
- compiler 对 graph-owned imported transitions 增加更严格校验:
|
||||
`graphOwnsTransitions == true` 时必须导入 texture-backed view
|
||||
|
||||
### 3. 重做 imported texture runtime view 解析
|
||||
|
||||
把 imported texture 的运行时解析从“固定返回 importedView”改成:
|
||||
|
||||
1. 如果 primary imported view 类型正好匹配请求,则直接返回 primary view
|
||||
2. 如果类型不匹配,但有底层 imported texture,则按需创建目标 view
|
||||
3. 运行时缓存这些按需创建的派生 view,并在 graph 执行结束后释放
|
||||
|
||||
要求:
|
||||
|
||||
- `ResolveTextureView(handle, viewType)` 对 imported / transient 路径统一
|
||||
- 派生 view 创建走 `RHIDevice`,不允许在 render graph 里做后端特化 cast
|
||||
- depth texture 不创建 RTV,color texture 不创建 DSV
|
||||
- 失败时返回空指针,由上层执行链路报错
|
||||
|
||||
### 4. 完成验证与归档
|
||||
|
||||
执行以下验证闭环:
|
||||
|
||||
1. `cmake --build . --config Debug --target XCEditor`
|
||||
2. 运行 old editor 冒烟 15 秒
|
||||
3. 检查 `editor/bin/Debug/editor.log` 出现 `SceneReady`
|
||||
4. plan 归档到 `docs/used`
|
||||
5. 使用规范 Conventional Commit 提交并推送
|
||||
|
||||
## 风险与边界
|
||||
|
||||
1. swapchain backbuffer 是否支持 SRV,取决于后端和资源创建方式;本阶段不为此额外改造 swapchain 资源描述
|
||||
2. 如果某个 imported view 不是 texture-backed view,本阶段不会伪造多视图能力
|
||||
3. 本阶段先解决“可正确建模并解析 imported texture view”的根问题,不扩展更高层 surface API
|
||||
@@ -0,0 +1,90 @@
|
||||
# SRP / URP Renderer Block Formalization Plan
|
||||
|
||||
时间:2026-04-22
|
||||
|
||||
## 背景
|
||||
|
||||
当前渲染主线已经完成了两件更底层的事情:
|
||||
|
||||
1. C++ 侧的 RenderGraph / runtime resource / stage contract 已经能稳定承接 managed SRP。
|
||||
2. managed 侧也已经有 `ScriptableRenderer / RendererFeature / RenderPass` 这套骨架,并且 post-process / final output 的 graph 绑定已经打通。
|
||||
|
||||
但 renderer 这一层还有一个明显的问题没有收口:
|
||||
|
||||
- `ScriptableRenderer` 现在还是把所有 pass 丢进一个总队列,然后在录制时按 `CameraFrameStage` 逐个扫描、过滤。
|
||||
- 这意味着 renderer 的“组织单位”依然是 stage,而不是 renderer 自己拥有的 block。
|
||||
- 对后续把阴影、体积、Gaussian、更多 scene feature 逐步迁到 URP 层不够友好,因为缺少稳定的 block 落点。
|
||||
|
||||
这一步的目标不是继续扩 RenderGraph 功能,也不是开始 deferred,而是先把 managed renderer 的组织方式收紧。
|
||||
|
||||
## 本阶段目标
|
||||
|
||||
把 managed `ScriptableRenderer` 从“单队列 + stage 过滤”重构成“显式 renderer block 录制”,并保持当前 C++ stage 边界不变。
|
||||
|
||||
目标结果:
|
||||
|
||||
1. `ScriptableRenderer` 内部显式识别 `ShadowCaster / DepthPrepass / MainOpaque / MainSkybox / MainTransparent / PostProcess / FinalOutput`。
|
||||
2. stage 仍然只是 native 执行边界,renderer 内部真正按 block 组织与录制。
|
||||
3. `UniversalRenderer` 后续迁移阴影、体积、Gaussian 等逻辑时,有稳定的 block 入口可以承接。
|
||||
4. 不引入新的兼容层,不保留“旧逻辑先留着”的临时路线。
|
||||
|
||||
## 范围
|
||||
|
||||
本阶段只做 managed SRP / URP 组织重构,不做:
|
||||
|
||||
- deferred rendering
|
||||
- shadow 算法升级
|
||||
- editor 侧面板与资源工作流
|
||||
- ObjectId 这类 editor-only 特性迁移
|
||||
|
||||
## 实施步骤
|
||||
|
||||
### 1. 补齐 renderer block 基础类型
|
||||
|
||||
新增 renderer block 枚举与辅助工具,统一维护:
|
||||
|
||||
- pass event -> renderer block
|
||||
- renderer block -> camera frame stage
|
||||
- renderer block 的运行时范围描述
|
||||
|
||||
### 2. 重构 ScriptableRenderer 的录制入口
|
||||
|
||||
保留 active pass queue 作为排序输入,但录制逻辑改为:
|
||||
|
||||
1. 先按 `RenderPassEvent` 排序构建 active pass queue
|
||||
2. 再根据 event range 构建 renderer block range
|
||||
3. 按当前 stage 对应的 block 顺序执行
|
||||
|
||||
也就是说:
|
||||
|
||||
- `MainScene` 不再是“扫完整队列找属于 MainScene 的 pass”
|
||||
- 而是显式录制 `MainOpaque -> MainSkybox -> MainTransparent`
|
||||
|
||||
### 3. 清理 stage-driven 痕迹
|
||||
|
||||
重点清理:
|
||||
|
||||
- `ScriptableRenderer` 内部 `renderPass.SupportsStage(...)` 式的全队列过滤
|
||||
- 把 `SupportsRendererRecording / RecordRenderer` 改成基于 block 判断
|
||||
|
||||
保留:
|
||||
|
||||
- native C++ 仍然通过 `CameraFrameStage` 调用 managed
|
||||
- `ScriptableRenderPass.SupportsStage(...)` 作为公共 API 兼容入口,但内部改为基于 block 推导
|
||||
|
||||
### 4. 验证主线不回退
|
||||
|
||||
要求:
|
||||
|
||||
1. `XCEditor` Debug 构建通过
|
||||
2. old editor 冒烟运行至少 10 秒
|
||||
3. `editor.log` 出现 `SceneReady`
|
||||
|
||||
## 完成标准
|
||||
|
||||
满足以下条件才算本阶段收口:
|
||||
|
||||
1. `ScriptableRenderer` 不再通过“单队列 + stage 过滤”驱动录制。
|
||||
2. renderer block 成为 managed renderer 内部的正式组织单位。
|
||||
3. `UniversalRenderer` 当前默认路径行为不回退。
|
||||
4. `XCEditor` 构建与 old editor 冒烟通过。
|
||||
@@ -0,0 +1,64 @@
|
||||
# SRP / URP Renderer Data Collection Plan
|
||||
|
||||
时间:2026-04-22
|
||||
|
||||
## 背景
|
||||
|
||||
上一阶段已经把 `ScriptableRendererData` 里的 `rendererFeatures` 生命周期收成了
|
||||
`ScriptableRendererFeatureCollection`,但 pipeline asset 这一层还有同类问题:
|
||||
|
||||
1. `RendererBackedRenderPipelineAsset` 直接持有并管理 `rendererDataList/defaultRendererIndex`
|
||||
2. renderer data 的默认创建、fallback 解析、重复引用释放、runtime hash 都散落在 asset 类里
|
||||
3. 这会让 asset 同时承担 authoring 表达和 runtime collection 管理两类职责
|
||||
|
||||
这和上一阶段收 `rendererFeatures` 之前的状态很像,也不利于后续继续往 Unity 风格的
|
||||
多个 renderer variant 演进。
|
||||
|
||||
## 目标
|
||||
|
||||
把 asset 层的 renderer data 管理正式收成一个 collection 边界。
|
||||
|
||||
阶段完成后要达到:
|
||||
|
||||
1. `RendererBackedRenderPipelineAsset` 不再散写 renderer data 列表生命周期细节
|
||||
2. 默认 renderer data 创建、index fallback、runtime hash、release 都有统一落点
|
||||
3. 不改变现有外部 authoring 入口,仍然保留 `rendererDataList/defaultRendererIndex`
|
||||
4. 为后续继续做 Unity 风格的 renderer variant / renderer profile 留出干净接缝
|
||||
|
||||
## 范围
|
||||
|
||||
本阶段只处理 renderer data collection 收口,不做:
|
||||
|
||||
- deferred renderer
|
||||
- editor inspector / 面板
|
||||
- public API 大改
|
||||
- 阴影或 post-process 功能扩展
|
||||
|
||||
## 实施步骤
|
||||
|
||||
### 1. 新增 ScriptableRendererDataCollection
|
||||
|
||||
职责:
|
||||
|
||||
- 统一解析 `rendererDataList`
|
||||
- 统一保证默认 renderer data 存在
|
||||
- 统一处理 `defaultRendererIndex` fallback
|
||||
- 统一计算 collection runtime hash
|
||||
- 统一释放 renderer data runtime 资源
|
||||
|
||||
### 2. 接入 RendererBackedRenderPipelineAsset
|
||||
|
||||
迁移内容:
|
||||
|
||||
- renderer data 解析
|
||||
- renderer 选择
|
||||
- runtime version 同步
|
||||
- release 流程
|
||||
|
||||
## 完成标准
|
||||
|
||||
满足以下条件才算本阶段收口:
|
||||
|
||||
1. `RendererBackedRenderPipelineAsset` 不再自己散写 renderer data collection 细节
|
||||
2. `XCEditor` 编译通过
|
||||
3. old editor 冒烟至少 10 秒通过
|
||||
@@ -0,0 +1,82 @@
|
||||
# SRP / URP Renderer Explicit Stage Planning Plan
|
||||
|
||||
时间:2026-04-22
|
||||
|
||||
## 背景
|
||||
|
||||
当前 managed `ScriptableRenderer / ScriptableRendererFeature / ScriptableRenderPass` 骨架已经可用,
|
||||
但 renderer 这一层还有一个不干净的旧接缝:
|
||||
|
||||
1. `ScriptableRenderer.FinalizeCameraFramePlan(...)` 仍然会根据 active pass queue 自动推断
|
||||
`ShadowCaster / DepthOnly / PostProcess / FinalOutput` stage
|
||||
2. 这个推断依赖一份“planning 阶段伪造的 `RenderingData(MainScene)`”,并不是真正的 renderer planning contract
|
||||
3. 结果是 renderer / feature 看起来已经在控制管线,但 stage ownership 仍然有一部分藏在基类启发式里
|
||||
|
||||
这不符合要对齐 Unity SRP / URP 的目标。
|
||||
|
||||
Unity 风格应该是:
|
||||
|
||||
- renderer / feature 显式决定本帧需要哪些阶段
|
||||
- native C++ 只负责 stage 执行、RenderGraph、scene draw substrate
|
||||
- 不能再让基类偷偷扫描 pass queue 替上层“猜阶段”
|
||||
|
||||
## 本阶段目标
|
||||
|
||||
把 managed renderer 的 stage planning 从“隐式推断”收成“显式声明”:
|
||||
|
||||
1. 去掉 `ScriptableRenderer` 基类里的 stage 推断逻辑
|
||||
2. 让真正拥有 pass 的 renderer / feature 自己在 planning hook 中申请所需 stage
|
||||
3. 保证现有 Universal 默认路径和 probe/sample 路径仍然能工作
|
||||
4. 完成后,renderer-driven SRP 的组织权更清晰,后续再继续往 renderer pass / renderer feature 主线推进
|
||||
|
||||
## 范围
|
||||
|
||||
本阶段只处理 managed renderer 的显式 stage planning,不做:
|
||||
|
||||
- deferred pipeline
|
||||
- shadow 资源系统迁移
|
||||
- RenderGraph 新功能扩展
|
||||
- editor 逻辑
|
||||
|
||||
## 实施步骤
|
||||
|
||||
### 1. 清理 `ScriptableRenderer` 基类隐式推断
|
||||
|
||||
删除以下旧逻辑:
|
||||
|
||||
- `CreatePlanningRenderingData(...)`
|
||||
- `ApplyInferredFullscreenStageRequests(...)`
|
||||
- `ApplyInferredStandaloneStageRequests(...)`
|
||||
- `HasQueuedPassForStage(...)`
|
||||
|
||||
`FinalizeCameraFramePlan(...)` 保持为空默认实现,不再隐式改 plan。
|
||||
|
||||
### 2. 把 stage planning 放回真正拥有 pass 的类型
|
||||
|
||||
至少补齐:
|
||||
|
||||
- `ColorScalePostProcessRendererFeature`
|
||||
- GameScripts 里的 fullscreen probe feature / renderer
|
||||
|
||||
原则:
|
||||
|
||||
- post-process feature 显式请求 `PostProcess`
|
||||
- 如需把结果交给 `FinalOutput`,则显式申请 graph-managed output color
|
||||
- 如有 final-output pass,则显式请求 `FinalOutput`
|
||||
|
||||
### 3. 验证当前主线不回退
|
||||
|
||||
要求:
|
||||
|
||||
1. `XCEditor` Debug 构建通过
|
||||
2. old editor 冒烟 15 秒通过
|
||||
3. `editor.log` 出现 `SceneReady`
|
||||
|
||||
## 完成标准
|
||||
|
||||
满足以下条件才算收口:
|
||||
|
||||
1. managed renderer 的 stage planning 不再依赖基类扫描 pass queue 的启发式
|
||||
2. 现有 Universal 默认 renderer 仍可运行
|
||||
3. probe/sample fullscreen renderer 走显式 planning 后仍能编译通过
|
||||
4. `XCEditor` 编译和 old editor 冒烟通过
|
||||
@@ -0,0 +1,70 @@
|
||||
# SRP / URP Renderer Feature Collection Plan
|
||||
|
||||
时间:2026-04-22
|
||||
|
||||
## 背景
|
||||
|
||||
当前 feature 层的 runtime boundary 已经基本收好,但 `renderer data` 这一层还有明显的结构问题:
|
||||
|
||||
1. `ScriptableRendererData` 直接持有并操作 `rendererFeatures` 数组。
|
||||
2. feature owner bind、active 遍历、runtime state hash、runtime release 这些逻辑在 `ScriptableRendererData` 里分散重复。
|
||||
3. `UniversalRendererData` 的默认 feature 组合也还是直接在 `CreateDefaultRendererFeatures()` 里硬编码构造。
|
||||
|
||||
这会导致:
|
||||
|
||||
- `renderer data` 既在做 renderer asset 表达,又在做 feature collection 运行时管理。
|
||||
- 默认 feature 组合没有正式落点,后续扩展不同 renderer profile 时不利于演进。
|
||||
|
||||
## 本阶段目标
|
||||
|
||||
把 `rendererFeatures` 这层正式收成 collection / factory 结构。
|
||||
|
||||
目标结果:
|
||||
|
||||
1. `ScriptableRendererFeatureCollection` 统一管理 feature 数组的 bind、active 遍历、hash、release。
|
||||
2. `ScriptableRendererData` 不再散写 feature 集合生命周期。
|
||||
3. `UniversalRendererData` 的默认 feature 组合改走明确工厂。
|
||||
|
||||
## 范围
|
||||
|
||||
本阶段只处理 renderer feature collection,不做:
|
||||
|
||||
- public renderer feature API 改造
|
||||
- deferred rendering
|
||||
- editor feature 分类面板
|
||||
- C++ host / RenderGraph 改造
|
||||
|
||||
## 实施步骤
|
||||
|
||||
### 1. 新增 ScriptableRendererFeatureCollection
|
||||
|
||||
职责:
|
||||
|
||||
- 持有 feature 数组引用
|
||||
- 统一 bind owner
|
||||
- 统一 active 遍历
|
||||
- 统一计算 collection hash
|
||||
- 统一 runtime release
|
||||
|
||||
### 2. 接入 ScriptableRendererData
|
||||
|
||||
迁移:
|
||||
|
||||
- `ConfigureCameraRenderRequestInstance`
|
||||
- `ConfigureCameraFramePlanInstance`
|
||||
- `ConfigureRenderSceneSetupInstance`
|
||||
- `ConfigureDirectionalShadowExecutionStateInstance`
|
||||
- `ReleaseRendererSetupCache`
|
||||
- renderer feature collection state sync
|
||||
|
||||
### 3. 抽离 Universal 默认 feature 工厂
|
||||
|
||||
新增 `UniversalDefaultRendererFeatureFactory`,负责默认 builtin feature 组合。
|
||||
|
||||
## 完成标准
|
||||
|
||||
满足以下条件才算本阶段收口:
|
||||
|
||||
1. `ScriptableRendererData` 不再自己散写 feature collection 生命周期细节。
|
||||
2. `UniversalRendererData` 默认 feature 组合走明确工厂。
|
||||
3. `XCEditor` 编译通过,old editor 冒烟通过。
|
||||
@@ -0,0 +1,100 @@
|
||||
# SRP / URP Request Policy And Scene Setup Seam Plan
|
||||
|
||||
## 背景
|
||||
|
||||
当前渲染模块已经基本形成了如下分层:
|
||||
|
||||
- C++ 层负责 Render Graph、frame execution、scene extraction、native scene draw backend、shadow runtime、fullscreen substrate 等执行底座
|
||||
- managed SRP / URP 层负责 renderer 选择、pass 组织、feature 组织、camera/frame planning 策略
|
||||
|
||||
但当前仍有两类关键策略口没有完全收干净:
|
||||
|
||||
1. `CameraRenderRequest` 阶段仍有部分默认策略固定在 C++ 层
|
||||
2. `RenderSceneSetup` 阶段 managed 层还缺少足够的配置能力,当前主要仍在调用 native default
|
||||
|
||||
这会导致 SRP / URP 虽然已经能组织 pass,但还没有完全接管“为什么这么渲染”的策略层。
|
||||
|
||||
## 本阶段目标
|
||||
|
||||
本阶段不继续搬运 native draw backend,不做 deferred,不扩张底层执行复杂度,只收策略边界。
|
||||
|
||||
### 目标一
|
||||
|
||||
把 request seam 做实,让 managed URP 可以直接接管以下 request-level 策略:
|
||||
|
||||
- camera stack / clear mode 读取
|
||||
- request clear flags 覆盖
|
||||
- directional shadow request 抑制与规划参数调整
|
||||
- renderer 选择仍保持由 managed 决定
|
||||
|
||||
### 目标二
|
||||
|
||||
为后续 scene setup seam 做准备,明确下一阶段 managed 需要接管的 scene setup 内容:
|
||||
|
||||
- environment policy
|
||||
- skybox policy
|
||||
- global shader keywords policy
|
||||
|
||||
## 本阶段实施步骤
|
||||
|
||||
### Step 1. 扩展 request context 与 camera managed API
|
||||
|
||||
补齐 managed 侧 request policy 所需的最小上下文:
|
||||
|
||||
- `Camera.clearMode`
|
||||
- `Camera.stackType`
|
||||
- `CameraRenderRequestContext.clearFlags`
|
||||
|
||||
要求:
|
||||
|
||||
- 通过 Mono internal call 打通
|
||||
- 不引入兼容层、废弃层或双轨 API
|
||||
- 保持 request 仍由 C++ 创建,但允许 managed 在 request 阶段覆盖策略结果
|
||||
|
||||
### Step 2. 把默认 request clear / shadow policy 收进 URP
|
||||
|
||||
在 `UniversalRenderPipelineAsset` 中接管默认 request policy:
|
||||
|
||||
- 依据 camera clear mode 和 stack type 解析 request clear flags
|
||||
- 继续在 managed 层控制 main light shadow request 是否保留
|
||||
- 继续在 managed 层控制 shadow planning settings
|
||||
|
||||
要求:
|
||||
|
||||
- 默认行为与当前引擎已有表现保持一致
|
||||
- native default policy 退化为底座 fallback,而不是 URP 主路径
|
||||
|
||||
### Step 3. 预留 scene setup seam 下一阶段入口
|
||||
|
||||
本阶段先不大改 scene setup,但要确认下一阶段的直接入口:
|
||||
|
||||
- `RenderSceneSetupContext` 需要扩展哪些显式设置能力
|
||||
- `UniversalRenderer.ConfigureRenderSceneSetup(...)` 之后如何从“调用 default”过渡为“显式配置环境与关键字”
|
||||
|
||||
## 收口标准
|
||||
|
||||
- managed 层可以读取 camera stack / clear mode
|
||||
- managed 层可以覆盖 request clear flags
|
||||
- URP 默认 clear / shadow request 策略由 managed 决定
|
||||
- `XCEditor` Debug 编译通过
|
||||
- 旧版 editor 冒烟通过
|
||||
|
||||
## 非目标
|
||||
|
||||
本阶段不做以下事项:
|
||||
|
||||
- deferred rendering
|
||||
- render graph 大改
|
||||
- native scene draw backend 搬迁
|
||||
- 阴影算法本体迁移到 managed
|
||||
- gaussian / volumetric native 执行实现迁移
|
||||
|
||||
## 完成情况
|
||||
|
||||
- 已补齐 managed request seam 所需的 `Camera.clearMode`、`Camera.stackType`、`CameraRenderRequestContext.clearFlags`
|
||||
- 已将 URP 默认 request clear policy 收进 managed `UniversalRenderPipelineAsset`
|
||||
- 已将 `RenderClearFlags` 收敛到 rendering core,移除 URP 包内重复定义
|
||||
- 已让 `UniversalRenderer.ConfigureRenderSceneSetup(...)` 从 bundled `UseDefaultSceneSetup()` 过渡为显式组合 environment / global keywords
|
||||
- 已补齐 `RenderSceneSetupContext.camera` 入口,便于下一阶段继续接管 scene setup policy
|
||||
- `XCEditor` Debug 编译通过
|
||||
- 旧版 editor 冒烟通过
|
||||
@@ -0,0 +1,31 @@
|
||||
# SRP/URP Shadow Boundary Closure Plan
|
||||
|
||||
日期:2026-04-21
|
||||
|
||||
## 背景
|
||||
|
||||
当前 SRP/URP 骨架已经基本成型,但阴影这条链路在 managed 与 native 之间还有一个关键边界没收干净:
|
||||
|
||||
1. `UniversalRenderPipelineAsset` / `UniversalRenderer` 已经在 managed 层表达阴影开关、stage 规划与 renderer 级别控制。
|
||||
2. native 侧仍保留阴影图分配与默认执行策略,这本身是当前阶段合理的 substrate。
|
||||
3. 但当 managed renderer 明确不想执行阴影时,如果只是不配置 execution state,host 仍可能回落到 native 默认阴影执行,导致 managed 决策失效。
|
||||
|
||||
这会让 shadow 的“策略在 managed,执行底座在 native”的边界重新变脏。
|
||||
|
||||
## 目标
|
||||
|
||||
1. 收紧 shadow execution 边界,确保 managed renderer 明确关闭阴影时,不会再落回 native 默认执行。
|
||||
2. 保持当前 native 阴影 runtime / surface allocation / default execution substrate 不变,不扩功能,不碰 deferred。
|
||||
3. 通过一次编译和旧版 editor 冒烟验证,尽快把这一个骨架口子收掉。
|
||||
|
||||
## 实施步骤
|
||||
|
||||
1. 修正 `UniversalRenderer.ConfigureDirectionalShadowExecutionState(...)`,让 shadow caster block 禁用或无阴影计划时显式清空 execution state,而不是隐式留给 host fallback。
|
||||
2. 复查这条路径的 host fallback 行为,确认 managed 明确配置后不会再重回 native 默认阴影执行。
|
||||
3. 重新编译 `XCEditor`,运行旧版 `editor/bin/Debug/XCEngine.exe` 冒烟至少 10 秒,确认 `SceneReady`。
|
||||
|
||||
## 完成判定
|
||||
|
||||
1. managed renderer 明确关闭阴影时,shadow execution state 会被显式清空。
|
||||
2. `cmake --build build --config Debug --target XCEditor` 成功。
|
||||
3. 旧版 editor 冒烟通过,日志出现新的 `SceneReady`。
|
||||
@@ -0,0 +1,85 @@
|
||||
# SRP / URP Stage-Scoped Pass Collection Plan
|
||||
|
||||
时间:2026-04-22
|
||||
|
||||
## 背景
|
||||
|
||||
上一阶段已经把 managed renderer 的执行组织收成了 renderer block:
|
||||
|
||||
- `ShadowCaster`
|
||||
- `DepthPrepass`
|
||||
- `MainOpaque`
|
||||
- `MainSkybox`
|
||||
- `MainTransparent`
|
||||
- `PostProcess`
|
||||
- `FinalOutput`
|
||||
|
||||
但当前还有一个没有完全收口的问题:
|
||||
|
||||
1. native C++ 这一层仍然按 `CameraFrameStage` 分阶段调用 managed renderer。
|
||||
2. `ScriptableRenderer.BuildPassQueue(...)` 也是每个 stage 都会执行一次。
|
||||
3. 可现在 renderer / feature 仍然可能在这个阶段里把所有 stage 的 pass 都先塞进总队列,再交给后面的 block 过滤。
|
||||
|
||||
这意味着:
|
||||
|
||||
- 组织方式虽然已经比之前清晰,但 pass collection 仍然混着跨 stage 的内容。
|
||||
- `UniversalRenderer` 自己对 block 的 ownership 也还不够直接。
|
||||
- 后续把 shadow / volumetric / gaussian 等能力继续往 URP 层迁时,边界会继续发虚。
|
||||
|
||||
## 本阶段目标
|
||||
|
||||
把 managed renderer 的 pass collection 也收成 stage-scoped,并同步把 `UniversalRenderer` 的内建 pass 入口拆成更清晰的 block-owned 结构。
|
||||
|
||||
目标结果:
|
||||
|
||||
1. 当前 stage 构建 pass queue 时,不再混入明显属于其他 stage 的 pass。
|
||||
2. `UniversalRenderer` 明确区分 shadow / depth / main scene / final output 这些 block-owned 入口。
|
||||
3. 继续保留现在的 `RenderPassEvent + RenderBlocks` 路线,不引入额外兼容层。
|
||||
|
||||
## 范围
|
||||
|
||||
本阶段只处理 managed SRP / URP 的 pass collection 与 block ownership,不做:
|
||||
|
||||
- deferred rendering
|
||||
- 阴影算法迁移
|
||||
- editor-only 渲染能力迁移
|
||||
- C++ RenderGraph 功能扩展
|
||||
|
||||
## 实施步骤
|
||||
|
||||
### 1. ScriptableRenderer pass collection stage-scoped 化
|
||||
|
||||
重构 `ScriptableRenderer`:
|
||||
|
||||
- 在 build active pass queue 时记录当前 `RenderingData.stage`
|
||||
- `EnqueuePass(...)` 在 pass queue build 期间只接受与当前 stage 匹配的 pass
|
||||
- 非 build 期间保持现有安全行为
|
||||
|
||||
这样可以让当前 stage 的 queue 从源头上变干净,而不是先混入、后过滤。
|
||||
|
||||
### 2. UniversalRenderer 显式按 block 组织内建 pass
|
||||
|
||||
重构 `UniversalRenderer.AddRenderPasses(...)`:
|
||||
|
||||
- `ShadowCaster` 只处理 shadow block
|
||||
- `DepthOnly` 只处理 depth prepass block
|
||||
- `MainScene` 只处理 opaque / skybox / transparent
|
||||
- `FinalOutput` 只处理 final output block
|
||||
|
||||
必要时同步清理内建 feature 的 stage 边界判断,避免继续依赖下游过滤。
|
||||
|
||||
### 3. 验证主线不回退
|
||||
|
||||
要求:
|
||||
|
||||
1. `XCEditor` Debug 构建通过
|
||||
2. old editor 冒烟至少 10 秒
|
||||
3. `editor.log` 出现 `SceneReady`
|
||||
|
||||
## 完成标准
|
||||
|
||||
满足以下条件才算本阶段收口:
|
||||
|
||||
1. active pass queue 的 collection 已经是 stage-scoped。
|
||||
2. `UniversalRenderer` 内建 pass ownership 更直接,不再在单个入口里混着所有 stage。
|
||||
3. `XCEditor` 编译与 old editor 冒烟通过。
|
||||
@@ -0,0 +1,48 @@
|
||||
# SRP/URP Standalone Stage Ownership Boundary Plan
|
||||
|
||||
日期:2026-04-21
|
||||
|
||||
## 背景
|
||||
|
||||
当前 SRP/URP 主线已经有了基本骨架,但 `ScriptableRenderPipelineHostAsset` 里仍然直接注册了三类 native standalone pass:
|
||||
|
||||
1. `BuiltinShadowCasterPass`
|
||||
2. `BuiltinDepthOnlyPass`
|
||||
3. `BuiltinObjectIdPass`
|
||||
|
||||
这会带来两个结构问题:
|
||||
|
||||
1. 通用 SRP host 和 builtin forward fallback 耦合在一起。`ScriptableRenderPipelineHost` 本应只负责 managed/native 桥接、stage recorder 绑定和 fallback 分发,不应该自己偷偷决定 builtin standalone stage 的具体实现。
|
||||
2. ownership 不清晰。managed URP 已经在 C# 层负责 shadow/depth 的 stage 规划和 render-graph 录制,但 native fallback 仍然挂在 host asset 上,导致“谁拥有这些 fallback pass”这个问题没有收口。
|
||||
|
||||
这一步不是做新功能,而是把这条边界收干净,让后续继续按 Unity 风格往 SRP + URP 分层推进。
|
||||
|
||||
## 目标
|
||||
|
||||
1. 让 `ScriptableRenderPipelineHost` 退回到真正的 host 角色,不再在 asset 层硬编码 builtin standalone pass。
|
||||
2. 让 builtin forward backend 显式拥有自己的 native standalone fallback pass。
|
||||
3. 保持当前运行结果不变:managed renderer 录制 stage 时优先走 managed;需要 native fallback 时,由 backend 明确提供。
|
||||
|
||||
## 实施步骤
|
||||
|
||||
1. 在 `BuiltinForward...Setup` 路径中显式配置 builtin forward pipeline 的 standalone fallback pass,而不是在 host asset 中配置。
|
||||
2. 调整 `ScriptableRenderPipelineHost::GetCameraFrameStandalonePass(...)`,让 host 在自身未持有 pass 时,从 backend 查询 standalone pass。
|
||||
3. 清理 `ScriptableRenderPipelineHostAsset` 中已过期的 builtin pass 注入逻辑。
|
||||
4. 重新编译旧版 `XCEditor`,运行旧版 editor 冒烟至少 10 秒,确认没有把 fallback 链路改坏。
|
||||
|
||||
## 完成判定
|
||||
|
||||
1. `ScriptableRenderPipelineHostAsset` 不再直接注册 builtin shadow/depth/object-id standalone pass。
|
||||
2. builtin forward backend 仍可为 fallback stage 提供 native standalone pass。
|
||||
3. `cmake --build . --config Debug --target XCEditor` 成功。
|
||||
4. 旧版 `editor/bin/Debug/XCEngine.exe` 冒烟通过,并出现新的 `SceneReady` 记录。
|
||||
|
||||
## 结果
|
||||
|
||||
1. `ScriptableRenderPipelineHostAsset` 已移除 builtin standalone pass 注入逻辑。
|
||||
2. builtin forward backend 现在在自身 setup 中显式注册 `ObjectId`、`DepthOnly`、`ShadowCaster` fallback pass。
|
||||
3. `ScriptableRenderPipelineHost` 现在会在自身未持有 standalone pass 时,向 backend 查询 fallback pass。
|
||||
4. 验证结果:
|
||||
`cmake --build . --config Debug --target XCEditor` 通过。
|
||||
旧版 editor 冒烟 15 秒通过。
|
||||
日志结果:`SceneReady elapsed_ms=5505 first_frame_ms=619`。
|
||||
@@ -0,0 +1,69 @@
|
||||
# SRP / URP UniversalPostProcessBlock Plan
|
||||
|
||||
时间:2026-04-22
|
||||
|
||||
## 背景
|
||||
|
||||
当前 `UniversalRenderer` 已经把这些 block 拆出来了:
|
||||
|
||||
- `UniversalShadowCasterBlock`
|
||||
- `UniversalDepthPrepassBlock`
|
||||
- `UniversalMainSceneBlock`
|
||||
- `UniversalFinalOutputBlock`
|
||||
|
||||
但 `post-process` 这一面还没有自己的正式落点:
|
||||
|
||||
1. fullscreen post-process stage planning 还散在具体 feature 里。
|
||||
2. `UniversalFinalOutputBlock` 又需要读取并调整 post-process stage 的 graph-managed output 状态。
|
||||
3. 结果是 post-process / final output 的协作语义分散在多个类里,不利于后续继续接更多 post-process feature。
|
||||
|
||||
## 本阶段目标
|
||||
|
||||
补齐 `UniversalPostProcessBlock`,把 post-process 共享 planning 语义收口到统一 helper。
|
||||
|
||||
目标结果:
|
||||
|
||||
1. `ColorScalePostProcessRendererFeature` 不再内联维护 fullscreen post-process planning 逻辑。
|
||||
2. `UniversalFinalOutputBlock` 不再直接手写 post-process stage promotion 逻辑。
|
||||
3. 后续新增更多 post-process feature 时,可以复用 `UniversalPostProcessBlock` 的共享行为。
|
||||
|
||||
## 范围
|
||||
|
||||
本阶段只处理 post-process / final output 共享 planning,不做:
|
||||
|
||||
- 新的 post-process feature API 设计
|
||||
- deferred rendering
|
||||
- C++ host / RenderGraph 改造
|
||||
|
||||
## 实施步骤
|
||||
|
||||
### 1. 新增 UniversalPostProcessBlock
|
||||
|
||||
职责:
|
||||
|
||||
- 统一请求 post-process fullscreen stage
|
||||
- 统一处理 graph-managed output color 的 promotion
|
||||
- 为 final output 提供 post-process color source 解析
|
||||
|
||||
### 2. 接入现有使用点
|
||||
|
||||
接入:
|
||||
|
||||
- `ColorScalePostProcessRendererFeature`
|
||||
- `UniversalFinalOutputBlock`
|
||||
|
||||
### 3. 验证
|
||||
|
||||
要求:
|
||||
|
||||
1. `XCEditor` Debug 构建通过
|
||||
2. old editor 冒烟至少 10 秒
|
||||
3. `editor.log` 出现 `SceneReady`
|
||||
|
||||
## 完成标准
|
||||
|
||||
满足以下条件才算本阶段收口:
|
||||
|
||||
1. post-process shared planning 已经集中到 `UniversalPostProcessBlock`。
|
||||
2. `ColorScalePostProcessRendererFeature` 与 `UniversalFinalOutputBlock` 都走统一 helper。
|
||||
3. `XCEditor` 编译与 old editor 冒烟通过。
|
||||
@@ -0,0 +1,80 @@
|
||||
# SRP / URP UniversalRenderer Block Ownership Plan
|
||||
|
||||
时间:2026-04-22
|
||||
|
||||
## 背景
|
||||
|
||||
当前主线已经做到:
|
||||
|
||||
1. managed renderer 的执行已经按 renderer block 组织。
|
||||
2. pass collection 也已经收成 stage-scoped。
|
||||
3. `UniversalRenderer` 现在会按 `ShadowCaster / DepthOnly / MainScene / FinalOutput` 分入口添加内建 pass。
|
||||
|
||||
但还有一个明显的结构问题:
|
||||
|
||||
- `UniversalRenderer` 自己仍然同时承担了 block planning、scene setup、shadow execution state、builtin pass setup 这些职责。
|
||||
- 虽然逻辑已经按 block 分段,但仍然都堆在一个类里。
|
||||
|
||||
这会直接影响下一阶段把更多能力往 URP 层迁:
|
||||
|
||||
- 没有稳定的 block owner 落点。
|
||||
- 以后 shadow / lighting / volumetric / gaussian / post-process 继续增强时,`UniversalRenderer` 会再次膨胀。
|
||||
|
||||
## 本阶段目标
|
||||
|
||||
把 `UniversalRenderer` 的内联 block 逻辑正式拆成 block controller / owner 类,让 renderer 自己退化成编排者。
|
||||
|
||||
目标结果:
|
||||
|
||||
1. `ShadowCaster` block 自己负责 stage planning、shadow execution state、builtin pass setup。
|
||||
2. `DepthPrepass` block 自己负责 planning 和 builtin pass setup。
|
||||
3. `MainScene` block 自己负责 scene pass setup,并承接 scene environment/setup 相关逻辑。
|
||||
4. `FinalOutput` block 自己负责 final output planning 与 builtin final color pass setup。
|
||||
5. `UniversalRenderer` 自己只负责拿 data、协调这些 block、暴露 renderer 级入口。
|
||||
|
||||
## 范围
|
||||
|
||||
本阶段只做 `UniversalRenderer` 内部 block ownership 拆分,不做:
|
||||
|
||||
- deferred rendering
|
||||
- 新的 renderer feature API
|
||||
- 阴影算法功能升级
|
||||
- C++ host / RenderGraph 扩展
|
||||
|
||||
## 实施步骤
|
||||
|
||||
### 1. 提取 block controller 类
|
||||
|
||||
新增内部 block controller:
|
||||
|
||||
- `UniversalShadowCasterBlock`
|
||||
- `UniversalDepthPrepassBlock`
|
||||
- `UniversalMainSceneBlock`
|
||||
- `UniversalFinalOutputBlock`
|
||||
|
||||
### 2. 迁移 block 职责
|
||||
|
||||
迁移内容:
|
||||
|
||||
- shadow stage planning
|
||||
- depth stage planning
|
||||
- final output planning
|
||||
- directional shadow execution state
|
||||
- render scene setup 中属于 main scene block 的内容
|
||||
- builtin pass configure / enqueue
|
||||
|
||||
### 3. 收紧 UniversalRenderer
|
||||
|
||||
`UniversalRenderer` 只保留:
|
||||
|
||||
- renderer data 获取
|
||||
- 调用各 block controller
|
||||
- renderer 级生命周期协调
|
||||
|
||||
## 完成标准
|
||||
|
||||
满足以下条件才算本阶段收口:
|
||||
|
||||
1. `UniversalRenderer` 不再内联维护大段 block-specific 逻辑。
|
||||
2. 四个核心 block 都有自己的 owner/controller 落点。
|
||||
3. `XCEditor` 编译通过,old editor 冒烟通过。
|
||||
BIN
docs/used/c.png
Normal file
BIN
docs/used/c.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 57 KiB |
BIN
docs/used/color.png
Normal file
BIN
docs/used/color.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 41 KiB |
@@ -539,6 +539,7 @@ add_library(XCEngine STATIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/Rendering/RenderSurface.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/Rendering/RenderSurfacePipelineUtils.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/Rendering/SceneRenderFeaturePass.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/Rendering/SceneRenderFeaturePassId.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/Rendering/SceneRenderFeatureHost.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/Rendering/ShaderVariantUtils.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/Rendering/Internal/RenderSurfacePipelineUtils.h
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include "../RHIResourceView.h"
|
||||
#include "../RHIEnums.h"
|
||||
#include "D3D12Texture.h"
|
||||
#include "D3D12Enums.h"
|
||||
|
||||
using Microsoft::WRL::ComPtr;
|
||||
@@ -15,7 +16,6 @@ namespace RHI {
|
||||
|
||||
class D3D12DescriptorHeap;
|
||||
class D3D12Buffer;
|
||||
|
||||
class D3D12ResourceView : public RHIResourceView {
|
||||
public:
|
||||
D3D12ResourceView();
|
||||
@@ -30,8 +30,10 @@ public:
|
||||
ResourceViewType GetViewType() const override { return m_viewType; }
|
||||
ResourceViewDimension GetDimension() const override { return m_dimension; }
|
||||
Format GetFormat() const override { return m_format; }
|
||||
RHITexture* GetTextureResource() const override { return m_texture; }
|
||||
|
||||
void SetOwnedHeap(std::unique_ptr<class D3D12DescriptorHeap> heap);
|
||||
void SetTextureResource(D3D12Texture* texture) { m_texture = texture; }
|
||||
|
||||
void InitializeAsRenderTarget(ID3D12Device* device, ID3D12Resource* resource,
|
||||
const D3D12_RENDER_TARGET_VIEW_DESC* desc,
|
||||
@@ -86,6 +88,7 @@ private:
|
||||
ResourceViewDimension m_dimension;
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE m_handle;
|
||||
ID3D12Resource* m_resource;
|
||||
D3D12Texture* m_texture;
|
||||
D3D12DescriptorHeap* m_heap;
|
||||
uint32_t m_slotIndex;
|
||||
std::unique_ptr<D3D12DescriptorHeap> m_ownedHeap;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "XCEngine/RHI/OpenGL/OpenGLFramebuffer.h"
|
||||
#include "XCEngine/RHI/OpenGL/OpenGLTexture.h"
|
||||
#include "XCEngine/RHI/RHIResourceView.h"
|
||||
#include "XCEngine/RHI/RHITypes.h"
|
||||
|
||||
@@ -71,7 +72,8 @@ public:
|
||||
uint32_t GetBufferSize() const { return m_bufferSize; }
|
||||
uint32_t GetBufferStride() const { return m_bufferStride; }
|
||||
const FramebufferAttachment& GetFramebufferAttachment() const { return m_framebufferAttachment; }
|
||||
const OpenGLTexture* GetTextureResource() const { return m_texture; }
|
||||
RHITexture* GetTextureResource() const override { return m_texture; }
|
||||
OpenGLTexture* GetOpenGLTextureResource() const { return m_texture; }
|
||||
|
||||
private:
|
||||
ResourceViewType m_viewType;
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
namespace XCEngine {
|
||||
namespace RHI {
|
||||
|
||||
class RHITexture;
|
||||
|
||||
class RHIResourceView {
|
||||
public:
|
||||
virtual ~RHIResourceView() = default;
|
||||
@@ -19,6 +21,9 @@ public:
|
||||
virtual ResourceViewType GetViewType() const = 0;
|
||||
virtual ResourceViewDimension GetDimension() const = 0;
|
||||
virtual Format GetFormat() const = 0;
|
||||
virtual RHITexture* GetTextureResource() const {
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
class RHIVertexBufferView : public RHIResourceView {
|
||||
|
||||
@@ -2,13 +2,12 @@
|
||||
|
||||
#include "XCEngine/RHI/RHIResourceView.h"
|
||||
#include "XCEngine/RHI/Vulkan/VulkanCommon.h"
|
||||
#include "XCEngine/RHI/Vulkan/VulkanTexture.h"
|
||||
|
||||
namespace XCEngine {
|
||||
namespace RHI {
|
||||
|
||||
class VulkanBuffer;
|
||||
class VulkanTexture;
|
||||
|
||||
class VulkanResourceView : public RHIResourceView {
|
||||
public:
|
||||
VulkanResourceView() = default;
|
||||
@@ -30,6 +29,7 @@ public:
|
||||
ResourceViewType GetViewType() const override { return m_viewType; }
|
||||
ResourceViewDimension GetDimension() const override { return m_dimension; }
|
||||
Format GetFormat() const override { return m_format; }
|
||||
RHITexture* GetTextureResource() const override { return m_texture; }
|
||||
|
||||
VulkanTexture* GetTexture() const { return m_texture; }
|
||||
VkImageView GetImageView() const { return m_imageView; }
|
||||
|
||||
@@ -48,6 +48,10 @@ public:
|
||||
SceneRenderInjectionPoint GetInjectionPoint() const override {
|
||||
return SceneRenderInjectionPoint::BeforeTransparent;
|
||||
}
|
||||
NativeSceneFeaturePassId GetNativeSceneFeaturePassId()
|
||||
const override {
|
||||
return NativeSceneFeaturePassId::BuiltinGaussianSplat;
|
||||
}
|
||||
bool Initialize(const RenderContext& context) override;
|
||||
bool IsActive(const RenderSceneData& sceneData) const override;
|
||||
bool Prepare(
|
||||
|
||||
@@ -43,6 +43,10 @@ public:
|
||||
SceneRenderInjectionPoint GetInjectionPoint() const override {
|
||||
return SceneRenderInjectionPoint::BeforeTransparent;
|
||||
}
|
||||
NativeSceneFeaturePassId GetNativeSceneFeaturePassId()
|
||||
const override {
|
||||
return NativeSceneFeaturePassId::BuiltinVolumetric;
|
||||
}
|
||||
bool Initialize(const RenderContext& context) override;
|
||||
bool IsActive(const RenderSceneData& sceneData) const override;
|
||||
bool Prepare(
|
||||
|
||||
@@ -32,6 +32,7 @@ private:
|
||||
RenderGraphTextureDesc desc = {};
|
||||
RenderGraphTextureKind kind = RenderGraphTextureKind::Transient;
|
||||
RHI::RHIResourceView* importedView = nullptr;
|
||||
RHI::RHITexture* importedTexture = nullptr;
|
||||
RenderGraphImportedTextureOptions importedOptions = {};
|
||||
};
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@ private:
|
||||
RenderGraphTextureDesc desc = {};
|
||||
RenderGraphTextureKind kind = RenderGraphTextureKind::Transient;
|
||||
RHI::RHIResourceView* importedView = nullptr;
|
||||
RHI::RHITexture* importedTexture = nullptr;
|
||||
RenderGraphImportedTextureOptions importedOptions = {};
|
||||
};
|
||||
|
||||
|
||||
@@ -104,7 +104,7 @@ struct RenderGraphTextureTransitionPlan {
|
||||
|
||||
struct RenderGraphExecutionContext {
|
||||
const RenderContext& renderContext;
|
||||
const RenderGraphRuntimeResources* runtimeResources = nullptr;
|
||||
RenderGraphRuntimeResources* runtimeResources = nullptr;
|
||||
|
||||
RHI::RHIResourceView* ResolveTextureView(
|
||||
RenderGraphTextureHandle handle,
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <XCEngine/Core/Asset/ResourceHandle.h>
|
||||
#include <XCEngine/Core/Containers/String.h>
|
||||
#include <XCEngine/Core/Math/Vector4.h>
|
||||
#include <XCEngine/Rendering/Builtin/BuiltinPassTypes.h>
|
||||
#include <XCEngine/Rendering/RenderPass.h>
|
||||
#include <XCEngine/Resources/Shader/Shader.h>
|
||||
#include <XCEngine/RHI/RHIEnums.h>
|
||||
@@ -27,6 +28,23 @@ public:
|
||||
RHI::RHIDescriptorSet* set = nullptr;
|
||||
};
|
||||
|
||||
struct BoundSetState {
|
||||
RHI::RHIResourceView* sourceColorTextureView = nullptr;
|
||||
std::vector<RHI::RHIResourceView*> materialTextureViews = {};
|
||||
};
|
||||
|
||||
struct PassResourceLayout {
|
||||
std::vector<BuiltinPassSetLayoutMetadata> setLayouts = {};
|
||||
std::vector<OwnedDescriptorSet> descriptorSets = {};
|
||||
std::vector<BoundSetState> boundSetStates = {};
|
||||
RHI::RHIPipelineLayout* pipelineLayout = nullptr;
|
||||
PassResourceBindingLocation passConstants = {};
|
||||
PassResourceBindingLocation sourceColorTexture = {};
|
||||
PassResourceBindingLocation linearClampSampler = {};
|
||||
uint32_t firstDescriptorSet = 0u;
|
||||
uint32_t descriptorSetCount = 0u;
|
||||
};
|
||||
|
||||
explicit BuiltinVectorFullscreenPass(
|
||||
const Math::Vector4& vectorPayload = Math::Vector4::One(),
|
||||
Containers::String shaderPath = {},
|
||||
@@ -51,7 +69,15 @@ public:
|
||||
private:
|
||||
bool EnsureInitialized(const RenderContext& renderContext, const RenderSurface& surface);
|
||||
bool CreateResources(const RenderContext& renderContext, const RenderSurface& surface);
|
||||
bool CreateOwnedDescriptorSet(
|
||||
const BuiltinPassSetLayoutMetadata& setLayout,
|
||||
OwnedDescriptorSet& descriptorSet);
|
||||
bool UpdateDescriptorSets(const RenderPassContext& context);
|
||||
RHI::RHIResourceView* ResolveExtraTextureView(
|
||||
const RenderPassContext& context,
|
||||
const BuiltinPassResourceBindingDesc& bindingDesc) const;
|
||||
void DestroyResources();
|
||||
void DestroyPassResourceLayout();
|
||||
void DestroyOwnedDescriptorSet(OwnedDescriptorSet& descriptorSet);
|
||||
|
||||
Containers::String m_shaderPath;
|
||||
@@ -64,12 +90,8 @@ private:
|
||||
uint32_t m_renderTargetSampleQuality = 0u;
|
||||
Resources::ResourceHandle<Resources::Shader> m_shader;
|
||||
RHI::RHISampler* m_sampler = nullptr;
|
||||
RHI::RHIPipelineLayout* m_pipelineLayout = nullptr;
|
||||
RHI::RHIPipelineState* m_pipelineState = nullptr;
|
||||
OwnedDescriptorSet m_constantsSet = {};
|
||||
OwnedDescriptorSet m_textureSet = {};
|
||||
OwnedDescriptorSet m_samplerSet = {};
|
||||
RHI::RHIResourceView* m_boundSourceColorView = nullptr;
|
||||
PassResourceLayout m_passLayout = {};
|
||||
};
|
||||
|
||||
} // namespace Passes
|
||||
|
||||
@@ -104,14 +104,6 @@ public:
|
||||
GetSharedPipelineBackendAsset() const {
|
||||
return nullptr;
|
||||
}
|
||||
virtual bool UsesNativeCameraFramePlanBaseline() const {
|
||||
return false;
|
||||
}
|
||||
virtual bool UsesNativeCameraFramePlanBaseline(
|
||||
int32_t rendererIndex) const {
|
||||
(void)rendererIndex;
|
||||
return UsesNativeCameraFramePlanBaseline();
|
||||
}
|
||||
virtual bool TryGetDefaultFinalColorSettings(FinalColorSettings&) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ public:
|
||||
bool RecordScenePhase(ScenePhase scenePhase);
|
||||
bool RecordSceneDrawSettings(const DrawSettings& drawSettings);
|
||||
bool RecordInjectionPoint(SceneRenderInjectionPoint injectionPoint);
|
||||
bool RecordFeaturePass(const Containers::String& featurePassName);
|
||||
bool RecordFeaturePass(NativeSceneFeaturePassId featurePassId);
|
||||
|
||||
private:
|
||||
SceneRenderFeaturePassBeginCallback BuildBeginRecordedPassCallback(
|
||||
|
||||
@@ -69,6 +69,9 @@ public:
|
||||
|
||||
private:
|
||||
bool EnsureInitialized(const RenderContext& context);
|
||||
RenderPass* ResolvePipelineBackendStandalonePass(
|
||||
CameraFrameStage stage,
|
||||
int32_t rendererIndex) const;
|
||||
void BindStageRecorderPipelineBackend();
|
||||
void ShutdownInitializedComponents();
|
||||
void ResetInitializationState();
|
||||
@@ -98,7 +101,6 @@ public:
|
||||
managedAssetRuntime);
|
||||
|
||||
std::unique_ptr<RenderPipeline> CreatePipeline() const override;
|
||||
void ConfigurePipeline(RenderPipeline& pipeline) const override;
|
||||
FinalColorSettings GetDefaultFinalColorSettings() const override;
|
||||
|
||||
private:
|
||||
|
||||
@@ -23,12 +23,18 @@ class RenderGraphBuilder;
|
||||
class RenderGraphBlackboard;
|
||||
|
||||
struct RenderPassContext {
|
||||
struct TextureBindingView {
|
||||
Containers::String resourceName = {};
|
||||
RHI::RHIResourceView* resourceView = nullptr;
|
||||
};
|
||||
|
||||
const RenderContext& renderContext;
|
||||
const RenderSurface& surface;
|
||||
const RenderSceneData& sceneData;
|
||||
const RenderSurface* sourceSurface = nullptr;
|
||||
RHI::RHIResourceView* sourceColorView = nullptr;
|
||||
RHI::ResourceStates sourceColorState = RHI::ResourceStates::Common;
|
||||
std::vector<TextureBindingView> textureBindings = {};
|
||||
};
|
||||
|
||||
inline RenderPassContext BuildRenderPassContext(
|
||||
@@ -39,7 +45,8 @@ inline RenderPassContext BuildRenderPassContext(
|
||||
executionContext.sceneData,
|
||||
executionContext.sourceSurface,
|
||||
executionContext.sourceColorView,
|
||||
executionContext.sourceColorState
|
||||
executionContext.sourceColorState,
|
||||
{}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,12 @@ struct RenderPassGraphIO {
|
||||
bool writeDepth = false;
|
||||
};
|
||||
|
||||
struct RenderPassGraphTextureBindingRequest {
|
||||
Containers::String resourceName = {};
|
||||
RenderGraphTextureHandle texture = {};
|
||||
RenderGraphTextureAspect aspect = RenderGraphTextureAspect::Color;
|
||||
};
|
||||
|
||||
inline RenderPassGraphIO BuildSourceColorFullscreenRasterPassGraphIO() {
|
||||
return {
|
||||
true,
|
||||
@@ -52,7 +58,9 @@ bool RecordCallbackRasterRenderPass(
|
||||
const RenderPassRenderGraphContext& context,
|
||||
const RenderPassGraphIO& io,
|
||||
RenderPassGraphExecutePassCallback executePassCallback,
|
||||
std::vector<RenderGraphTextureHandle> additionalReadTextures = {});
|
||||
std::vector<RenderGraphTextureHandle> additionalReadTextures = {},
|
||||
std::vector<RenderGraphTextureHandle> additionalReadDepthTextures = {},
|
||||
std::vector<RenderPassGraphTextureBindingRequest> textureBindingRequests = {});
|
||||
|
||||
bool RecordRasterRenderPass(
|
||||
RenderPass& pass,
|
||||
@@ -100,12 +108,14 @@ inline bool RecordSourceColorFullscreenCallbackRasterPass(
|
||||
inline bool RecordColorDepthCallbackRasterPass(
|
||||
const RenderPassRenderGraphContext& context,
|
||||
RenderPassGraphExecutePassCallback executePassCallback,
|
||||
std::vector<RenderGraphTextureHandle> additionalReadTextures = {}) {
|
||||
std::vector<RenderGraphTextureHandle> additionalReadTextures = {},
|
||||
std::vector<RenderGraphTextureHandle> additionalReadDepthTextures = {}) {
|
||||
return RecordCallbackRasterRenderPass(
|
||||
context,
|
||||
BuildColorDepthRasterPassGraphIO(),
|
||||
std::move(executePassCallback),
|
||||
std::move(additionalReadTextures));
|
||||
std::move(additionalReadTextures),
|
||||
std::move(additionalReadDepthTextures));
|
||||
}
|
||||
|
||||
} // namespace Rendering
|
||||
|
||||
@@ -23,7 +23,7 @@ public:
|
||||
bool* recordedAnyPass = nullptr) const;
|
||||
bool RecordFeaturePass(
|
||||
const SceneRenderFeaturePassRenderGraphContext& context,
|
||||
const Containers::String& featurePassName,
|
||||
NativeSceneFeaturePassId featurePassId,
|
||||
bool* recordedPass = nullptr) const;
|
||||
bool Execute(
|
||||
const FrameExecutionContext& executionContext,
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <XCEngine/Rendering/Graph/RenderGraphTypes.h>
|
||||
#include <XCEngine/Rendering/RenderPass.h>
|
||||
#include <XCEngine/Rendering/RenderSurface.h>
|
||||
#include <XCEngine/Rendering/SceneRenderFeaturePassId.h>
|
||||
|
||||
#include <functional>
|
||||
|
||||
@@ -44,6 +45,11 @@ public:
|
||||
return SceneRenderInjectionPoint::BeforeTransparent;
|
||||
}
|
||||
|
||||
virtual NativeSceneFeaturePassId
|
||||
GetNativeSceneFeaturePassId() const {
|
||||
return NativeSceneFeaturePassId::Invalid;
|
||||
}
|
||||
|
||||
bool SupportsInjectionPoint(SceneRenderInjectionPoint injectionPoint) const {
|
||||
return GetInjectionPoint() == injectionPoint;
|
||||
}
|
||||
|
||||
15
engine/include/XCEngine/Rendering/SceneRenderFeaturePassId.h
Normal file
15
engine/include/XCEngine/Rendering/SceneRenderFeaturePassId.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Rendering {
|
||||
|
||||
enum class NativeSceneFeaturePassId : uint32_t {
|
||||
Invalid = 0u,
|
||||
BuiltinGaussianSplat = 1u,
|
||||
BuiltinVolumetric = 2u
|
||||
};
|
||||
|
||||
} // namespace Rendering
|
||||
} // namespace XCEngine
|
||||
@@ -106,20 +106,43 @@ inline UITabStripLayoutResult ArrangeUITabStrip(
|
||||
const float gap = (std::max)(0.0f, metrics.tabGap);
|
||||
const float totalGapWidth = gap * static_cast<float>(desiredHeaderWidths.size() - 1u);
|
||||
const float availableTabsWidth = (std::max)(0.0f, bounds.width - totalGapWidth);
|
||||
const float minTabWidth = (std::max)(0.0f, metrics.tabMinWidth);
|
||||
|
||||
std::vector<float> resolvedHeaderWidths = {};
|
||||
resolvedHeaderWidths.reserve(desiredHeaderWidths.size());
|
||||
|
||||
float totalDesiredWidth = 0.0f;
|
||||
float totalMinimumWidth = 0.0f;
|
||||
for (float width : desiredHeaderWidths) {
|
||||
totalDesiredWidth += (std::max)(0.0f, width);
|
||||
const float desiredWidth = (std::max)((std::max)(0.0f, width), minTabWidth);
|
||||
resolvedHeaderWidths.push_back(desiredWidth);
|
||||
totalDesiredWidth += desiredWidth;
|
||||
totalMinimumWidth += minTabWidth;
|
||||
}
|
||||
|
||||
const float scale = totalDesiredWidth > 0.0f && totalDesiredWidth > availableTabsWidth
|
||||
? availableTabsWidth / totalDesiredWidth
|
||||
: 1.0f;
|
||||
if (totalDesiredWidth > availableTabsWidth && totalDesiredWidth > 0.0f) {
|
||||
if (totalMinimumWidth > 0.0f && totalMinimumWidth >= availableTabsWidth) {
|
||||
const float minWidthScale = availableTabsWidth / totalMinimumWidth;
|
||||
for (float& width : resolvedHeaderWidths) {
|
||||
width = minTabWidth * minWidthScale;
|
||||
}
|
||||
} else {
|
||||
const float totalShrinkableWidth = totalDesiredWidth - totalMinimumWidth;
|
||||
const float overflowWidth = totalDesiredWidth - availableTabsWidth;
|
||||
const float excessScale = totalShrinkableWidth > 0.0f
|
||||
? ((std::max)(totalShrinkableWidth - overflowWidth, 0.0f) / totalShrinkableWidth)
|
||||
: 0.0f;
|
||||
for (float& width : resolvedHeaderWidths) {
|
||||
const float shrinkableWidth = (std::max)(width - minTabWidth, 0.0f);
|
||||
width = minTabWidth + shrinkableWidth * excessScale;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float cursorX = bounds.x;
|
||||
for (std::size_t index = 0; index < desiredHeaderWidths.size(); ++index) {
|
||||
const float width = totalDesiredWidth > 0.0f
|
||||
? (std::max)(0.0f, desiredHeaderWidths[index]) * scale
|
||||
? resolvedHeaderWidths[index]
|
||||
: availableTabsWidth / static_cast<float>(desiredHeaderWidths.size());
|
||||
result.tabHeaderRects[index] = UIRect(cursorX, bounds.y, width, headerHeight);
|
||||
cursorX += width + gap;
|
||||
|
||||
@@ -1597,6 +1597,7 @@ RHIResourceView* D3D12Device::CreateRenderTargetView(RHITexture* texture, const
|
||||
}
|
||||
|
||||
view->InitializeAsRenderTarget(m_device.Get(), resource, &rtvDesc, heap.get(), 0);
|
||||
view->SetTextureResource(d3d12Texture);
|
||||
view->SetOwnedHeap(std::move(heap));
|
||||
|
||||
return view;
|
||||
@@ -1619,6 +1620,7 @@ RHIResourceView* D3D12Device::CreateDepthStencilView(RHITexture* texture, const
|
||||
}
|
||||
|
||||
view->InitializeAsDepthStencil(m_device.Get(), resource, &dsvDesc, heap.get(), 0);
|
||||
view->SetTextureResource(d3d12Texture);
|
||||
view->SetOwnedHeap(std::move(heap));
|
||||
return view;
|
||||
}
|
||||
@@ -1738,6 +1740,7 @@ RHIResourceView* D3D12Device::CreateShaderResourceView(RHITexture* texture, cons
|
||||
}
|
||||
|
||||
view->InitializeAsShaderResource(m_device.Get(), resource, &srvDesc, heap.get(), 0);
|
||||
view->SetTextureResource(d3d12Texture);
|
||||
if (IsDepthFormat(format)) {
|
||||
view->SetFormat(format);
|
||||
}
|
||||
@@ -1815,6 +1818,7 @@ RHIResourceView* D3D12Device::CreateUnorderedAccessView(RHITexture* texture, con
|
||||
}
|
||||
|
||||
view->InitializeAsUnorderedAccess(m_device.Get(), resource, &uavDesc, heap.get(), 0);
|
||||
view->SetTextureResource(d3d12Texture);
|
||||
view->SetOwnedHeap(std::move(heap));
|
||||
return view;
|
||||
}
|
||||
|
||||
@@ -111,6 +111,7 @@ D3D12ResourceView::D3D12ResourceView()
|
||||
, m_dimension(ResourceViewDimension::Unknown)
|
||||
, m_handle({0})
|
||||
, m_resource(nullptr)
|
||||
, m_texture(nullptr)
|
||||
, m_heap(nullptr)
|
||||
, m_slotIndex(0)
|
||||
, m_ownedHeap(nullptr)
|
||||
@@ -127,6 +128,7 @@ D3D12ResourceView::~D3D12ResourceView() {
|
||||
void D3D12ResourceView::Shutdown() {
|
||||
m_handle = {};
|
||||
m_resource = nullptr;
|
||||
m_texture = nullptr;
|
||||
if (m_ownedHeap) {
|
||||
m_ownedHeap->Shutdown();
|
||||
m_ownedHeap.reset();
|
||||
|
||||
@@ -52,7 +52,7 @@ bool GetOpenGLClearTargetExtent(const OpenGLResourceView* view, GLsizei& width,
|
||||
return false;
|
||||
}
|
||||
|
||||
const OpenGLTexture* texture = view->GetTextureResource();
|
||||
const OpenGLTexture* texture = view->GetOpenGLTextureResource();
|
||||
if (texture == nullptr) {
|
||||
return false;
|
||||
}
|
||||
@@ -631,7 +631,7 @@ void OpenGLCommandList::TransitionBarrier(RHIResourceView* resource, ResourceSta
|
||||
(void)stateBefore;
|
||||
if (resource != nullptr && resource->IsValid()) {
|
||||
OpenGLResourceView* view = static_cast<OpenGLResourceView*>(resource);
|
||||
OpenGLTexture* texture = const_cast<OpenGLTexture*>(view->GetTextureResource());
|
||||
OpenGLTexture* texture = view->GetOpenGLTextureResource();
|
||||
if (texture != nullptr) {
|
||||
texture->SetState(stateAfter);
|
||||
}
|
||||
@@ -750,7 +750,7 @@ void OpenGLCommandList::SetRenderTargets(uint32_t count, RHIResourceView** rende
|
||||
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
auto* view = static_cast<OpenGLResourceView*>(renderTargets[i]);
|
||||
const OpenGLTexture* texture = view != nullptr ? view->GetTextureResource() : nullptr;
|
||||
const OpenGLTexture* texture = view != nullptr ? view->GetOpenGLTextureResource() : nullptr;
|
||||
if (texture != nullptr) {
|
||||
width = texture->GetWidth();
|
||||
height = texture->GetHeight();
|
||||
@@ -760,7 +760,7 @@ void OpenGLCommandList::SetRenderTargets(uint32_t count, RHIResourceView** rende
|
||||
|
||||
if ((width == 0 || height == 0) && depthStencil != nullptr) {
|
||||
auto* dsv = static_cast<OpenGLResourceView*>(depthStencil);
|
||||
const OpenGLTexture* depthTexture = dsv != nullptr ? dsv->GetTextureResource() : nullptr;
|
||||
const OpenGLTexture* depthTexture = dsv != nullptr ? dsv->GetOpenGLTextureResource() : nullptr;
|
||||
if (depthTexture != nullptr) {
|
||||
width = depthTexture->GetWidth();
|
||||
height = depthTexture->GetHeight();
|
||||
@@ -782,7 +782,7 @@ void OpenGLCommandList::SetRenderTargets(uint32_t count, RHIResourceView** rende
|
||||
} else {
|
||||
ReleaseComposedFramebuffer();
|
||||
OpenGLResourceView* view = static_cast<OpenGLResourceView*>(renderTargets[0]);
|
||||
const OpenGLTexture* texture = view != nullptr ? view->GetTextureResource() : nullptr;
|
||||
const OpenGLTexture* texture = view != nullptr ? view->GetOpenGLTextureResource() : nullptr;
|
||||
if (texture != nullptr) {
|
||||
m_currentRenderTargetWidth = texture->GetWidth();
|
||||
m_currentRenderTargetHeight = texture->GetHeight();
|
||||
@@ -795,7 +795,7 @@ void OpenGLCommandList::SetRenderTargets(uint32_t count, RHIResourceView** rende
|
||||
ReleaseComposedFramebuffer();
|
||||
OpenGLResourceView* dsv = static_cast<OpenGLResourceView*>(depthStencil);
|
||||
if (dsv && dsv->IsValid()) {
|
||||
const OpenGLTexture* depthTexture = dsv->GetTextureResource();
|
||||
const OpenGLTexture* depthTexture = dsv->GetOpenGLTextureResource();
|
||||
if (depthTexture != nullptr) {
|
||||
m_currentRenderTargetWidth = depthTexture->GetWidth();
|
||||
m_currentRenderTargetHeight = depthTexture->GetHeight();
|
||||
@@ -1056,8 +1056,8 @@ void OpenGLCommandList::CopyResource(RHIResourceView* dst, RHIResourceView* src)
|
||||
|
||||
GLuint dstTex = dstView->GetTexture();
|
||||
GLuint srcTex = srcView->GetTexture();
|
||||
const OpenGLTexture* dstTexture = dstView->GetTextureResource();
|
||||
const OpenGLTexture* srcTexture = srcView->GetTextureResource();
|
||||
const OpenGLTexture* dstTexture = dstView->GetOpenGLTextureResource();
|
||||
const OpenGLTexture* srcTexture = srcView->GetOpenGLTextureResource();
|
||||
if (dstTex && srcTex && dstTexture != nullptr && srcTexture != nullptr) {
|
||||
const GLuint srcTarget = ToOpenGL(srcTexture->GetOpenGLType());
|
||||
const GLuint dstTarget = ToOpenGL(dstTexture->GetOpenGLType());
|
||||
|
||||
@@ -196,7 +196,7 @@ void OpenGLDescriptorSet::Update(uint32_t offset, RHIResourceView* view) {
|
||||
}
|
||||
|
||||
binding->textureIds[0] = glView->GetTexture();
|
||||
if (const OpenGLTexture* texture = glView->GetTextureResource()) {
|
||||
if (const OpenGLTexture* texture = glView->GetOpenGLTextureResource()) {
|
||||
binding->textureTargets[0] = static_cast<uint32_t>(ToOpenGL(texture->GetOpenGLType()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "Rendering/Execution/Internal/CameraFrameGraph/Executor.h"
|
||||
#include "Rendering/GraphicsSettingsState.h"
|
||||
#include "Rendering/Internal/RenderPipelineFactory.h"
|
||||
#include "Rendering/Passes/BuiltinObjectIdPass.h"
|
||||
#include "Rendering/Pipelines/ManagedScriptableRenderPipelineAsset.h"
|
||||
#include "Rendering/RenderPipelineAsset.h"
|
||||
#include "Rendering/RenderSurface.h"
|
||||
@@ -29,6 +30,14 @@ bool IsManagedPipelineAsset(
|
||||
pipelineAsset.get()) != nullptr;
|
||||
}
|
||||
|
||||
void ConfigureTopLevelToolingPasses(RenderPipeline& pipeline) {
|
||||
// Object-id is a tooling/editor request. It should live on the
|
||||
// top-level pipeline used by CameraRenderer, not on a scene backend.
|
||||
pipeline.SetCameraFrameStandalonePass(
|
||||
CameraFrameStage::ObjectId,
|
||||
std::make_unique<Passes::BuiltinObjectIdPass>());
|
||||
}
|
||||
|
||||
RenderPipelineStageSupportContext BuildStageSupportContext(
|
||||
const CameraFramePlan& plan,
|
||||
CameraFrameStage stage) {
|
||||
@@ -124,6 +133,10 @@ void CameraRenderer::ResetPipeline(std::unique_ptr<RenderPipeline> pipeline) {
|
||||
&m_pipelineAsset);
|
||||
}
|
||||
|
||||
if (m_pipeline != nullptr) {
|
||||
ConfigureTopLevelToolingPasses(*m_pipeline);
|
||||
}
|
||||
|
||||
m_managedPipelineEnvironmentGeneration =
|
||||
UsesManagedPipelineBinding()
|
||||
? GetGraphicsSettingsState().GetEnvironmentGeneration()
|
||||
|
||||
@@ -87,6 +87,8 @@ RenderGraphTextureHandle RenderGraphBuilder::ImportTexture(
|
||||
resource.desc = desc;
|
||||
resource.kind = RenderGraphTextureKind::Imported;
|
||||
resource.importedView = importedView;
|
||||
resource.importedTexture =
|
||||
importedView != nullptr ? importedView->GetTextureResource() : nullptr;
|
||||
resource.importedOptions = importedOptions;
|
||||
m_graph.m_textures.push_back(resource);
|
||||
|
||||
|
||||
@@ -115,9 +115,9 @@ bool RenderGraphCompiler::Compile(
|
||||
|
||||
if (texture.kind == RenderGraphTextureKind::Imported &&
|
||||
texture.importedOptions.graphOwnsTransitions &&
|
||||
texture.importedView == nullptr) {
|
||||
texture.importedTexture == nullptr) {
|
||||
WriteError(
|
||||
Containers::String("RenderGraph imported texture requires a valid view when graph owns transitions: ") +
|
||||
Containers::String("RenderGraph imported texture requires a texture-backed view when graph owns transitions: ") +
|
||||
texture.name,
|
||||
outErrorMessage);
|
||||
return false;
|
||||
@@ -237,6 +237,7 @@ bool RenderGraphCompiler::Compile(
|
||||
compiledTexture.desc = graph.m_textures[textureIndex].desc;
|
||||
compiledTexture.kind = graph.m_textures[textureIndex].kind;
|
||||
compiledTexture.importedView = graph.m_textures[textureIndex].importedView;
|
||||
compiledTexture.importedTexture = graph.m_textures[textureIndex].importedTexture;
|
||||
compiledTexture.importedOptions = graph.m_textures[textureIndex].importedOptions;
|
||||
outCompiledGraph.m_textures.push_back(std::move(compiledTexture));
|
||||
|
||||
|
||||
@@ -40,6 +40,26 @@ RenderGraphTextureViewType ResolveBarrierViewType(RHI::ResourceStates state) {
|
||||
: RenderGraphTextureViewType::ShaderResource;
|
||||
}
|
||||
|
||||
RHI::ResourceViewType ResolveRequestedResourceViewType(
|
||||
RenderGraphTextureViewType viewType) {
|
||||
switch (viewType) {
|
||||
case RenderGraphTextureViewType::RenderTarget:
|
||||
return RHI::ResourceViewType::RenderTarget;
|
||||
case RenderGraphTextureViewType::DepthStencil:
|
||||
return RHI::ResourceViewType::DepthStencil;
|
||||
case RenderGraphTextureViewType::UnorderedAccess:
|
||||
return RHI::ResourceViewType::UnorderedAccess;
|
||||
case RenderGraphTextureViewType::ShaderResource:
|
||||
default:
|
||||
return RHI::ResourceViewType::ShaderResource;
|
||||
}
|
||||
}
|
||||
|
||||
bool IsTextureViewDimension(RHI::ResourceViewDimension dimension) {
|
||||
return dimension != RHI::ResourceViewDimension::Unknown &&
|
||||
!RHI::IsBufferResourceViewDimension(dimension);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
class RenderGraphRuntimeResources {
|
||||
@@ -62,7 +82,10 @@ public:
|
||||
for (size_t textureIndex = 0u; textureIndex < m_graph.m_textures.size(); ++textureIndex) {
|
||||
const CompiledRenderGraph::CompiledTexture& texture = m_graph.m_textures[textureIndex];
|
||||
const RenderGraphTextureLifetime& lifetime = m_graph.m_textureLifetimes[textureIndex];
|
||||
TextureAllocation& allocation = m_textureAllocations[textureIndex];
|
||||
if (texture.kind == RenderGraphTextureKind::Imported) {
|
||||
allocation.texture = texture.importedTexture;
|
||||
allocation.primaryImportedView = texture.importedView;
|
||||
m_textureStates[textureIndex] = texture.importedOptions.initialState;
|
||||
}
|
||||
|
||||
@@ -105,29 +128,23 @@ public:
|
||||
|
||||
RHI::RHIResourceView* ResolveTextureView(
|
||||
RenderGraphTextureHandle handle,
|
||||
RenderGraphTextureViewType viewType) const {
|
||||
RenderGraphTextureViewType viewType,
|
||||
const RenderContext& renderContext) {
|
||||
if (!handle.IsValid() || handle.index >= m_graph.m_textures.size()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const CompiledRenderGraph::CompiledTexture& texture = m_graph.m_textures[handle.index];
|
||||
TextureAllocation& allocation = m_textureAllocations[handle.index];
|
||||
if (texture.kind == RenderGraphTextureKind::Imported) {
|
||||
return texture.importedView;
|
||||
return ResolveImportedTextureView(
|
||||
texture,
|
||||
allocation,
|
||||
viewType,
|
||||
renderContext);
|
||||
}
|
||||
|
||||
const TextureAllocation& allocation = m_textureAllocations[handle.index];
|
||||
switch (viewType) {
|
||||
case RenderGraphTextureViewType::RenderTarget:
|
||||
return allocation.renderTargetView;
|
||||
case RenderGraphTextureViewType::DepthStencil:
|
||||
return allocation.depthStencilView;
|
||||
case RenderGraphTextureViewType::ShaderResource:
|
||||
return allocation.shaderResourceView;
|
||||
case RenderGraphTextureViewType::UnorderedAccess:
|
||||
return allocation.unorderedAccessView;
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
return ResolveCachedView(allocation, viewType);
|
||||
}
|
||||
|
||||
bool TryGetTextureDesc(
|
||||
@@ -158,7 +175,6 @@ public:
|
||||
const CompiledRenderGraph::CompiledTexture& texture = m_graph.m_textures[textureIndex];
|
||||
if (texture.kind != RenderGraphTextureKind::Imported ||
|
||||
!texture.importedOptions.graphOwnsTransitions ||
|
||||
texture.importedView == nullptr ||
|
||||
textureIndex >= m_graph.m_textureLifetimes.size() ||
|
||||
!m_graph.m_textureLifetimes[textureIndex].used ||
|
||||
!IsGraphManagedTransientState(texture.importedOptions.finalState)) {
|
||||
@@ -208,8 +224,197 @@ private:
|
||||
RHI::RHIResourceView* depthStencilView = nullptr;
|
||||
RHI::RHIResourceView* shaderResourceView = nullptr;
|
||||
RHI::RHIResourceView* unorderedAccessView = nullptr;
|
||||
RHI::RHIResourceView* primaryImportedView = nullptr;
|
||||
bool ownsTexture = false;
|
||||
};
|
||||
|
||||
static RHI::RHIResourceView* ResolveCachedView(
|
||||
const TextureAllocation& allocation,
|
||||
RenderGraphTextureViewType viewType) {
|
||||
switch (viewType) {
|
||||
case RenderGraphTextureViewType::RenderTarget:
|
||||
return allocation.renderTargetView;
|
||||
case RenderGraphTextureViewType::DepthStencil:
|
||||
return allocation.depthStencilView;
|
||||
case RenderGraphTextureViewType::ShaderResource:
|
||||
return allocation.shaderResourceView;
|
||||
case RenderGraphTextureViewType::UnorderedAccess:
|
||||
return allocation.unorderedAccessView;
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static RHI::RHIResourceView*& ResolveCachedViewSlot(
|
||||
TextureAllocation& allocation,
|
||||
RenderGraphTextureViewType viewType) {
|
||||
switch (viewType) {
|
||||
case RenderGraphTextureViewType::RenderTarget:
|
||||
return allocation.renderTargetView;
|
||||
case RenderGraphTextureViewType::DepthStencil:
|
||||
return allocation.depthStencilView;
|
||||
case RenderGraphTextureViewType::ShaderResource:
|
||||
return allocation.shaderResourceView;
|
||||
case RenderGraphTextureViewType::UnorderedAccess:
|
||||
default:
|
||||
return allocation.unorderedAccessView;
|
||||
}
|
||||
}
|
||||
|
||||
static RHI::ResourceViewDimension ResolveDefaultImportedViewDimension(
|
||||
const CompiledRenderGraph::CompiledTexture& texture) {
|
||||
const RHI::TextureType textureType =
|
||||
static_cast<RHI::TextureType>(texture.desc.textureType);
|
||||
const bool isMultisampled = texture.desc.sampleCount > 1u;
|
||||
|
||||
switch (textureType) {
|
||||
case RHI::TextureType::Texture1D:
|
||||
return RHI::ResourceViewDimension::Texture1D;
|
||||
case RHI::TextureType::Texture2DArray:
|
||||
return isMultisampled
|
||||
? RHI::ResourceViewDimension::Texture2DMSArray
|
||||
: RHI::ResourceViewDimension::Texture2DArray;
|
||||
case RHI::TextureType::Texture3D:
|
||||
return RHI::ResourceViewDimension::Texture3D;
|
||||
case RHI::TextureType::TextureCube:
|
||||
return RHI::ResourceViewDimension::TextureCube;
|
||||
case RHI::TextureType::TextureCubeArray:
|
||||
return RHI::ResourceViewDimension::TextureCubeArray;
|
||||
case RHI::TextureType::Texture2D:
|
||||
default:
|
||||
return isMultisampled
|
||||
? RHI::ResourceViewDimension::Texture2DMS
|
||||
: RHI::ResourceViewDimension::Texture2D;
|
||||
}
|
||||
}
|
||||
|
||||
static RHI::Format ResolveImportedViewFormat(
|
||||
const CompiledRenderGraph::CompiledTexture& texture,
|
||||
const TextureAllocation& allocation) {
|
||||
if (allocation.primaryImportedView != nullptr &&
|
||||
allocation.primaryImportedView->GetFormat() != RHI::Format::Unknown) {
|
||||
return allocation.primaryImportedView->GetFormat();
|
||||
}
|
||||
|
||||
if (allocation.texture != nullptr &&
|
||||
allocation.texture->GetFormat() != RHI::Format::Unknown) {
|
||||
return allocation.texture->GetFormat();
|
||||
}
|
||||
|
||||
return static_cast<RHI::Format>(texture.desc.format);
|
||||
}
|
||||
|
||||
static RHI::ResourceViewDimension ResolveImportedViewDimension(
|
||||
const CompiledRenderGraph::CompiledTexture& texture,
|
||||
const TextureAllocation& allocation) {
|
||||
if (allocation.primaryImportedView != nullptr &&
|
||||
IsTextureViewDimension(allocation.primaryImportedView->GetDimension())) {
|
||||
return allocation.primaryImportedView->GetDimension();
|
||||
}
|
||||
|
||||
return ResolveDefaultImportedViewDimension(texture);
|
||||
}
|
||||
|
||||
static bool CanCreateImportedView(
|
||||
const CompiledRenderGraph::CompiledTexture& texture,
|
||||
RenderGraphTextureViewType viewType) {
|
||||
const bool isDepthTexture =
|
||||
IsDepthFormat(static_cast<RHI::Format>(texture.desc.format));
|
||||
switch (viewType) {
|
||||
case RenderGraphTextureViewType::RenderTarget:
|
||||
return !isDepthTexture;
|
||||
case RenderGraphTextureViewType::DepthStencil:
|
||||
return isDepthTexture;
|
||||
case RenderGraphTextureViewType::ShaderResource:
|
||||
return true;
|
||||
case RenderGraphTextureViewType::UnorderedAccess:
|
||||
return !isDepthTexture;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
RHI::RHIResourceView* ResolveImportedTextureView(
|
||||
const CompiledRenderGraph::CompiledTexture& texture,
|
||||
TextureAllocation& allocation,
|
||||
RenderGraphTextureViewType viewType,
|
||||
const RenderContext& renderContext) {
|
||||
if (allocation.primaryImportedView != nullptr &&
|
||||
allocation.primaryImportedView->GetViewType() ==
|
||||
ResolveRequestedResourceViewType(viewType) &&
|
||||
allocation.primaryImportedView->IsValid()) {
|
||||
return allocation.primaryImportedView;
|
||||
}
|
||||
|
||||
RHI::RHIResourceView*& cachedView =
|
||||
ResolveCachedViewSlot(allocation, viewType);
|
||||
if (cachedView != nullptr) {
|
||||
return cachedView;
|
||||
}
|
||||
|
||||
if (!CanCreateImportedView(texture, viewType) ||
|
||||
allocation.texture == nullptr ||
|
||||
renderContext.device == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
cachedView = CreateImportedTextureView(
|
||||
texture,
|
||||
allocation,
|
||||
viewType,
|
||||
renderContext);
|
||||
return cachedView;
|
||||
}
|
||||
|
||||
static void DestroyOwnedView(RHI::RHIResourceView*& view) {
|
||||
if (view == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
view->Shutdown();
|
||||
delete view;
|
||||
view = nullptr;
|
||||
}
|
||||
|
||||
RHI::RHIResourceView* CreateImportedTextureView(
|
||||
const CompiledRenderGraph::CompiledTexture& texture,
|
||||
const TextureAllocation& allocation,
|
||||
RenderGraphTextureViewType viewType,
|
||||
const RenderContext& renderContext) {
|
||||
if (renderContext.device == nullptr || allocation.texture == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RHI::ResourceViewDesc viewDesc = {};
|
||||
const RHI::Format viewFormat =
|
||||
ResolveImportedViewFormat(texture, allocation);
|
||||
if (viewFormat != RHI::Format::Unknown) {
|
||||
viewDesc.format = static_cast<Core::uint32>(viewFormat);
|
||||
}
|
||||
viewDesc.dimension = ResolveImportedViewDimension(texture, allocation);
|
||||
|
||||
switch (viewType) {
|
||||
case RenderGraphTextureViewType::RenderTarget:
|
||||
return renderContext.device->CreateRenderTargetView(
|
||||
allocation.texture,
|
||||
viewDesc);
|
||||
case RenderGraphTextureViewType::DepthStencil:
|
||||
return renderContext.device->CreateDepthStencilView(
|
||||
allocation.texture,
|
||||
viewDesc);
|
||||
case RenderGraphTextureViewType::ShaderResource:
|
||||
return renderContext.device->CreateShaderResourceView(
|
||||
allocation.texture,
|
||||
viewDesc);
|
||||
case RenderGraphTextureViewType::UnorderedAccess:
|
||||
return renderContext.device->CreateUnorderedAccessView(
|
||||
allocation.texture,
|
||||
viewDesc);
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool ShouldGraphManageTransitions(RenderGraphTextureHandle handle) const {
|
||||
if (!handle.IsValid() || handle.index >= m_graph.m_textures.size()) {
|
||||
return false;
|
||||
@@ -240,8 +445,21 @@ private:
|
||||
return true;
|
||||
}
|
||||
|
||||
RHI::RHIResourceView* resourceView =
|
||||
ResolveTextureView(handle, ResolveBarrierViewType(targetState));
|
||||
const CompiledRenderGraph::CompiledTexture& texture =
|
||||
m_graph.m_textures[handle.index];
|
||||
TextureAllocation& allocation = m_textureAllocations[handle.index];
|
||||
RHI::RHIResourceView* resourceView = nullptr;
|
||||
if (texture.kind == RenderGraphTextureKind::Imported &&
|
||||
allocation.primaryImportedView != nullptr &&
|
||||
allocation.primaryImportedView->GetTextureResource() != nullptr &&
|
||||
allocation.primaryImportedView->IsValid()) {
|
||||
resourceView = allocation.primaryImportedView;
|
||||
} else {
|
||||
resourceView = ResolveTextureView(
|
||||
handle,
|
||||
ResolveBarrierViewType(targetState),
|
||||
renderContext);
|
||||
}
|
||||
if (resourceView == nullptr) {
|
||||
if (outErrorMessage != nullptr) {
|
||||
*outErrorMessage =
|
||||
@@ -260,35 +478,19 @@ private:
|
||||
}
|
||||
|
||||
static void DestroyTextureAllocation(TextureAllocation& allocation) {
|
||||
if (allocation.renderTargetView != nullptr) {
|
||||
allocation.renderTargetView->Shutdown();
|
||||
delete allocation.renderTargetView;
|
||||
allocation.renderTargetView = nullptr;
|
||||
}
|
||||
DestroyOwnedView(allocation.renderTargetView);
|
||||
DestroyOwnedView(allocation.depthStencilView);
|
||||
DestroyOwnedView(allocation.shaderResourceView);
|
||||
DestroyOwnedView(allocation.unorderedAccessView);
|
||||
|
||||
if (allocation.depthStencilView != nullptr) {
|
||||
allocation.depthStencilView->Shutdown();
|
||||
delete allocation.depthStencilView;
|
||||
allocation.depthStencilView = nullptr;
|
||||
}
|
||||
|
||||
if (allocation.shaderResourceView != nullptr) {
|
||||
allocation.shaderResourceView->Shutdown();
|
||||
delete allocation.shaderResourceView;
|
||||
allocation.shaderResourceView = nullptr;
|
||||
}
|
||||
|
||||
if (allocation.unorderedAccessView != nullptr) {
|
||||
allocation.unorderedAccessView->Shutdown();
|
||||
delete allocation.unorderedAccessView;
|
||||
allocation.unorderedAccessView = nullptr;
|
||||
}
|
||||
|
||||
if (allocation.texture != nullptr) {
|
||||
if (allocation.ownsTexture && allocation.texture != nullptr) {
|
||||
allocation.texture->Shutdown();
|
||||
delete allocation.texture;
|
||||
allocation.texture = nullptr;
|
||||
}
|
||||
|
||||
allocation.texture = nullptr;
|
||||
allocation.primaryImportedView = nullptr;
|
||||
allocation.ownsTexture = false;
|
||||
}
|
||||
|
||||
bool TextureRequiresUnorderedAccess(Core::uint32 textureIndex) const {
|
||||
@@ -327,6 +529,7 @@ private:
|
||||
DestroyTextureAllocation(allocation);
|
||||
return false;
|
||||
}
|
||||
allocation.ownsTexture = true;
|
||||
|
||||
RHI::ResourceViewDesc viewDesc = {};
|
||||
viewDesc.format = texture.desc.format;
|
||||
@@ -353,22 +556,25 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
if (!isDepthTexture) {
|
||||
allocation.shaderResourceView =
|
||||
renderContext.device->CreateShaderResourceView(allocation.texture, viewDesc);
|
||||
if (allocation.shaderResourceView == nullptr) {
|
||||
allocation.shaderResourceView =
|
||||
renderContext.device->CreateShaderResourceView(
|
||||
allocation.texture,
|
||||
viewDesc);
|
||||
if (allocation.shaderResourceView == nullptr) {
|
||||
DestroyTextureAllocation(allocation);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isDepthTexture &&
|
||||
requiresUnorderedAccess) {
|
||||
allocation.unorderedAccessView =
|
||||
renderContext.device->CreateUnorderedAccessView(
|
||||
allocation.texture,
|
||||
viewDesc);
|
||||
if (allocation.unorderedAccessView == nullptr) {
|
||||
DestroyTextureAllocation(allocation);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (requiresUnorderedAccess) {
|
||||
allocation.unorderedAccessView =
|
||||
renderContext.device->CreateUnorderedAccessView(allocation.texture, viewDesc);
|
||||
if (allocation.unorderedAccessView == nullptr) {
|
||||
DestroyTextureAllocation(allocation);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -389,7 +595,10 @@ RHI::RHIResourceView* RenderGraphExecutionContext::ResolveTextureView(
|
||||
RenderGraphTextureHandle handle,
|
||||
RenderGraphTextureViewType viewType) const {
|
||||
return runtimeResources != nullptr
|
||||
? runtimeResources->ResolveTextureView(handle, viewType)
|
||||
? runtimeResources->ResolveTextureView(
|
||||
handle,
|
||||
viewType,
|
||||
renderContext)
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,15 +5,9 @@
|
||||
|
||||
#include "Rendering/Execution/DirectionalShadowExecutionState.h"
|
||||
#include "Rendering/Pipelines/BuiltinForwardPipeline.h"
|
||||
#include "Rendering/Pipelines/Internal/BuiltinForwardSceneSetup.h"
|
||||
#include "Rendering/Pipelines/ManagedScriptableRenderPipelineAsset.h"
|
||||
#include "Rendering/Pipelines/ScriptableRenderPipelineHost.h"
|
||||
#include "Rendering/Passes/BuiltinDepthOnlyPass.h"
|
||||
#include "Rendering/Passes/BuiltinObjectIdPass.h"
|
||||
#include "Rendering/Passes/BuiltinShadowCasterPass.h"
|
||||
|
||||
#include <mutex>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Rendering {
|
||||
@@ -29,167 +23,6 @@ CreateBuiltinForwardPipelineRendererAsset() {
|
||||
return s_builtinForwardPipelineAsset;
|
||||
}
|
||||
|
||||
std::unique_ptr<RenderPass> CreateBuiltinDepthOnlyStandalonePass() {
|
||||
return std::make_unique<Passes::BuiltinDepthOnlyPass>();
|
||||
}
|
||||
|
||||
std::unique_ptr<RenderPass> CreateBuiltinObjectIdStandalonePass() {
|
||||
return std::make_unique<Passes::BuiltinObjectIdPass>();
|
||||
}
|
||||
|
||||
std::unique_ptr<RenderPass> CreateBuiltinShadowCasterStandalonePass() {
|
||||
return std::make_unique<Passes::BuiltinShadowCasterPass>();
|
||||
}
|
||||
|
||||
using PipelineBackendAssetRegistry =
|
||||
std::unordered_map<std::string, PipelineBackendAssetFactory>;
|
||||
using CameraFrameStandalonePassRegistry =
|
||||
std::unordered_map<std::string, CameraFrameStandalonePassFactory>;
|
||||
using CameraFramePlanPolicyRegistry =
|
||||
std::unordered_map<std::string, CameraFramePlanPolicy>;
|
||||
using DirectionalShadowExecutionPolicyRegistry =
|
||||
std::unordered_map<std::string, DirectionalShadowExecutionPolicy>;
|
||||
|
||||
PipelineBackendAssetRegistry& GetPipelineBackendAssetRegistry() {
|
||||
static PipelineBackendAssetRegistry registry = {};
|
||||
return registry;
|
||||
}
|
||||
|
||||
CameraFrameStandalonePassRegistry& GetCameraFrameStandalonePassRegistry() {
|
||||
static CameraFrameStandalonePassRegistry registry = {};
|
||||
return registry;
|
||||
}
|
||||
|
||||
CameraFramePlanPolicyRegistry& GetCameraFramePlanPolicyRegistry() {
|
||||
static CameraFramePlanPolicyRegistry registry = {};
|
||||
return registry;
|
||||
}
|
||||
|
||||
DirectionalShadowExecutionPolicyRegistry&
|
||||
GetDirectionalShadowExecutionPolicyRegistry() {
|
||||
static DirectionalShadowExecutionPolicyRegistry registry = {};
|
||||
return registry;
|
||||
}
|
||||
|
||||
std::unordered_set<std::string>& GetBuiltinPipelineBackendAssetKeys() {
|
||||
static std::unordered_set<std::string> builtinKeys = {};
|
||||
return builtinKeys;
|
||||
}
|
||||
|
||||
std::unordered_set<std::string>& GetBuiltinCameraFrameStandalonePassKeys() {
|
||||
static std::unordered_set<std::string> builtinKeys = {};
|
||||
return builtinKeys;
|
||||
}
|
||||
|
||||
std::unordered_set<std::string>& GetBuiltinCameraFramePlanPolicyKeys() {
|
||||
static std::unordered_set<std::string> builtinKeys = {};
|
||||
return builtinKeys;
|
||||
}
|
||||
|
||||
std::unordered_set<std::string>&
|
||||
GetBuiltinDirectionalShadowExecutionPolicyKeys() {
|
||||
static std::unordered_set<std::string> builtinKeys = {};
|
||||
return builtinKeys;
|
||||
}
|
||||
|
||||
std::mutex& GetPipelineBackendAssetRegistryMutex() {
|
||||
static std::mutex mutex;
|
||||
return mutex;
|
||||
}
|
||||
|
||||
std::mutex& GetCameraFrameStandalonePassRegistryMutex() {
|
||||
static std::mutex mutex;
|
||||
return mutex;
|
||||
}
|
||||
|
||||
std::mutex& GetCameraFramePlanPolicyRegistryMutex() {
|
||||
static std::mutex mutex;
|
||||
return mutex;
|
||||
}
|
||||
|
||||
std::mutex& GetDirectionalShadowExecutionPolicyRegistryMutex() {
|
||||
static std::mutex mutex;
|
||||
return mutex;
|
||||
}
|
||||
|
||||
void EnsureBuiltinPipelineBackendAssetRegistryInitialized() {
|
||||
static const bool initialized = []() {
|
||||
PipelineBackendAssetRegistry& registry =
|
||||
GetPipelineBackendAssetRegistry();
|
||||
registry.emplace(
|
||||
"BuiltinForward",
|
||||
&CreateBuiltinForwardPipelineRendererAsset);
|
||||
GetBuiltinPipelineBackendAssetKeys().insert("BuiltinForward");
|
||||
return true;
|
||||
}();
|
||||
(void)initialized;
|
||||
}
|
||||
|
||||
void EnsureBuiltinCameraFrameStandalonePassRegistryInitialized() {
|
||||
static const bool initialized = []() {
|
||||
CameraFrameStandalonePassRegistry& registry =
|
||||
GetCameraFrameStandalonePassRegistry();
|
||||
registry.emplace(
|
||||
"BuiltinDepthOnly",
|
||||
&CreateBuiltinDepthOnlyStandalonePass);
|
||||
registry.emplace(
|
||||
"BuiltinObjectId",
|
||||
&CreateBuiltinObjectIdStandalonePass);
|
||||
registry.emplace(
|
||||
"BuiltinShadowCaster",
|
||||
&CreateBuiltinShadowCasterStandalonePass);
|
||||
std::unordered_set<std::string>& builtinKeys =
|
||||
GetBuiltinCameraFrameStandalonePassKeys();
|
||||
builtinKeys.insert("BuiltinDepthOnly");
|
||||
builtinKeys.insert("BuiltinObjectId");
|
||||
builtinKeys.insert("BuiltinShadowCaster");
|
||||
return true;
|
||||
}();
|
||||
(void)initialized;
|
||||
}
|
||||
|
||||
void EnsureBuiltinCameraFramePlanPolicyRegistryInitialized() {
|
||||
static const bool initialized = []() {
|
||||
CameraFramePlanPolicyRegistry& registry =
|
||||
GetCameraFramePlanPolicyRegistry();
|
||||
registry.emplace(
|
||||
"BuiltinDefaultCameraFramePlan",
|
||||
[](CameraFramePlan& plan,
|
||||
const FinalColorSettings& defaultFinalColorSettings) {
|
||||
ApplyDefaultRenderPipelineAssetCameraFramePlanPolicy(
|
||||
plan,
|
||||
defaultFinalColorSettings);
|
||||
});
|
||||
GetBuiltinCameraFramePlanPolicyKeys().insert(
|
||||
"BuiltinDefaultCameraFramePlan");
|
||||
return true;
|
||||
}();
|
||||
(void)initialized;
|
||||
}
|
||||
|
||||
void EnsureBuiltinDirectionalShadowExecutionPolicyRegistryInitialized() {
|
||||
static const bool initialized = []() {
|
||||
DirectionalShadowExecutionPolicyRegistry& registry =
|
||||
GetDirectionalShadowExecutionPolicyRegistry();
|
||||
registry.emplace(
|
||||
"BuiltinDirectionalShadow",
|
||||
[](const CameraFramePlan& plan,
|
||||
const DirectionalShadowSurfaceAllocation& shadowAllocation,
|
||||
DirectionalShadowExecutionState& shadowState) {
|
||||
ApplyDefaultRenderPipelineDirectionalShadowExecutionPolicy(
|
||||
plan,
|
||||
shadowAllocation,
|
||||
shadowState);
|
||||
return shadowState.shadowCasterRequest.IsValid() &&
|
||||
shadowState.shadowData.IsValid();
|
||||
});
|
||||
GetBuiltinDirectionalShadowExecutionPolicyKeys().insert(
|
||||
"BuiltinDirectionalShadow");
|
||||
return true;
|
||||
}();
|
||||
(void)initialized;
|
||||
}
|
||||
|
||||
std::unique_ptr<SceneDrawBackend> TryCreateSceneDrawBackendFromAsset(
|
||||
const std::shared_ptr<const RenderPipelineAsset>& asset) {
|
||||
if (asset == nullptr) {
|
||||
@@ -221,266 +54,12 @@ std::shared_ptr<const RenderPipelineAsset> CreateFallbackRenderPipelineAsset() {
|
||||
return std::make_shared<Pipelines::ScriptableRenderPipelineHostAsset>();
|
||||
}
|
||||
|
||||
bool RegisterPipelineBackendAssetFactory(
|
||||
const std::string& key,
|
||||
PipelineBackendAssetFactory factory) {
|
||||
if (key.empty() || !factory) {
|
||||
return false;
|
||||
}
|
||||
|
||||
EnsureBuiltinPipelineBackendAssetRegistryInitialized();
|
||||
|
||||
std::lock_guard<std::mutex> lock(
|
||||
GetPipelineBackendAssetRegistryMutex());
|
||||
PipelineBackendAssetRegistry& registry =
|
||||
GetPipelineBackendAssetRegistry();
|
||||
if (registry.find(key) != registry.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
registry.emplace(key, std::move(factory));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UnregisterPipelineBackendAssetFactory(const std::string& key) {
|
||||
if (key.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
EnsureBuiltinPipelineBackendAssetRegistryInitialized();
|
||||
|
||||
std::lock_guard<std::mutex> lock(
|
||||
GetPipelineBackendAssetRegistryMutex());
|
||||
if (GetBuiltinPipelineBackendAssetKeys().find(key) !=
|
||||
GetBuiltinPipelineBackendAssetKeys().end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
PipelineBackendAssetRegistry& registry =
|
||||
GetPipelineBackendAssetRegistry();
|
||||
return registry.erase(key) != 0u;
|
||||
}
|
||||
|
||||
std::shared_ptr<const RenderPipelineAsset> CreateDefaultPipelineBackendAsset() {
|
||||
static const std::shared_ptr<const RenderPipelineAsset> s_defaultAsset =
|
||||
CreateBuiltinForwardPipelineRendererAsset();
|
||||
return s_defaultAsset;
|
||||
}
|
||||
|
||||
std::shared_ptr<const RenderPipelineAsset> CreatePipelineBackendAssetByKey(
|
||||
const std::string& key) {
|
||||
if (key.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
EnsureBuiltinPipelineBackendAssetRegistryInitialized();
|
||||
|
||||
std::lock_guard<std::mutex> lock(
|
||||
GetPipelineBackendAssetRegistryMutex());
|
||||
const PipelineBackendAssetRegistry& registry =
|
||||
GetPipelineBackendAssetRegistry();
|
||||
const auto it = registry.find(key);
|
||||
if (it == registry.end() || !it->second) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return it->second();
|
||||
}
|
||||
|
||||
bool RegisterCameraFrameStandalonePassFactory(
|
||||
const std::string& key,
|
||||
CameraFrameStandalonePassFactory factory) {
|
||||
if (key.empty() || !factory) {
|
||||
return false;
|
||||
}
|
||||
|
||||
EnsureBuiltinCameraFrameStandalonePassRegistryInitialized();
|
||||
|
||||
std::lock_guard<std::mutex> lock(
|
||||
GetCameraFrameStandalonePassRegistryMutex());
|
||||
CameraFrameStandalonePassRegistry& registry =
|
||||
GetCameraFrameStandalonePassRegistry();
|
||||
if (registry.find(key) != registry.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
registry.emplace(key, std::move(factory));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UnregisterCameraFrameStandalonePassFactory(
|
||||
const std::string& key) {
|
||||
if (key.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
EnsureBuiltinCameraFrameStandalonePassRegistryInitialized();
|
||||
|
||||
std::lock_guard<std::mutex> lock(
|
||||
GetCameraFrameStandalonePassRegistryMutex());
|
||||
if (GetBuiltinCameraFrameStandalonePassKeys().find(key) !=
|
||||
GetBuiltinCameraFrameStandalonePassKeys().end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CameraFrameStandalonePassRegistry& registry =
|
||||
GetCameraFrameStandalonePassRegistry();
|
||||
return registry.erase(key) != 0u;
|
||||
}
|
||||
|
||||
std::unique_ptr<RenderPass> CreateCameraFrameStandalonePassByKey(
|
||||
const std::string& key) {
|
||||
if (key.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
EnsureBuiltinCameraFrameStandalonePassRegistryInitialized();
|
||||
|
||||
std::lock_guard<std::mutex> lock(
|
||||
GetCameraFrameStandalonePassRegistryMutex());
|
||||
const CameraFrameStandalonePassRegistry& registry =
|
||||
GetCameraFrameStandalonePassRegistry();
|
||||
const auto it = registry.find(key);
|
||||
if (it == registry.end() || !it->second) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return it->second();
|
||||
}
|
||||
|
||||
bool RegisterCameraFramePlanPolicy(
|
||||
const std::string& key,
|
||||
CameraFramePlanPolicy policy) {
|
||||
if (key.empty() || !policy) {
|
||||
return false;
|
||||
}
|
||||
|
||||
EnsureBuiltinCameraFramePlanPolicyRegistryInitialized();
|
||||
|
||||
std::lock_guard<std::mutex> lock(
|
||||
GetCameraFramePlanPolicyRegistryMutex());
|
||||
CameraFramePlanPolicyRegistry& registry =
|
||||
GetCameraFramePlanPolicyRegistry();
|
||||
if (registry.find(key) != registry.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
registry.emplace(key, std::move(policy));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UnregisterCameraFramePlanPolicy(
|
||||
const std::string& key) {
|
||||
if (key.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
EnsureBuiltinCameraFramePlanPolicyRegistryInitialized();
|
||||
|
||||
std::lock_guard<std::mutex> lock(
|
||||
GetCameraFramePlanPolicyRegistryMutex());
|
||||
if (GetBuiltinCameraFramePlanPolicyKeys().find(key) !=
|
||||
GetBuiltinCameraFramePlanPolicyKeys().end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CameraFramePlanPolicyRegistry& registry =
|
||||
GetCameraFramePlanPolicyRegistry();
|
||||
return registry.erase(key) != 0u;
|
||||
}
|
||||
|
||||
bool ApplyCameraFramePlanPolicyByKey(
|
||||
const std::string& key,
|
||||
CameraFramePlan& plan,
|
||||
const FinalColorSettings& defaultFinalColorSettings) {
|
||||
if (key.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
EnsureBuiltinCameraFramePlanPolicyRegistryInitialized();
|
||||
|
||||
std::lock_guard<std::mutex> lock(
|
||||
GetCameraFramePlanPolicyRegistryMutex());
|
||||
const CameraFramePlanPolicyRegistry& registry =
|
||||
GetCameraFramePlanPolicyRegistry();
|
||||
const auto it = registry.find(key);
|
||||
if (it == registry.end() || !it->second) {
|
||||
return false;
|
||||
}
|
||||
|
||||
it->second(
|
||||
plan,
|
||||
defaultFinalColorSettings);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RegisterDirectionalShadowExecutionPolicy(
|
||||
const std::string& key,
|
||||
DirectionalShadowExecutionPolicy policy) {
|
||||
if (key.empty() || !policy) {
|
||||
return false;
|
||||
}
|
||||
|
||||
EnsureBuiltinDirectionalShadowExecutionPolicyRegistryInitialized();
|
||||
|
||||
std::lock_guard<std::mutex> lock(
|
||||
GetDirectionalShadowExecutionPolicyRegistryMutex());
|
||||
DirectionalShadowExecutionPolicyRegistry& registry =
|
||||
GetDirectionalShadowExecutionPolicyRegistry();
|
||||
if (registry.find(key) != registry.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
registry.emplace(key, std::move(policy));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UnregisterDirectionalShadowExecutionPolicy(
|
||||
const std::string& key) {
|
||||
if (key.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
EnsureBuiltinDirectionalShadowExecutionPolicyRegistryInitialized();
|
||||
|
||||
std::lock_guard<std::mutex> lock(
|
||||
GetDirectionalShadowExecutionPolicyRegistryMutex());
|
||||
if (GetBuiltinDirectionalShadowExecutionPolicyKeys().find(key) !=
|
||||
GetBuiltinDirectionalShadowExecutionPolicyKeys().end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
DirectionalShadowExecutionPolicyRegistry& registry =
|
||||
GetDirectionalShadowExecutionPolicyRegistry();
|
||||
return registry.erase(key) != 0u;
|
||||
}
|
||||
|
||||
bool ConfigureDirectionalShadowExecutionStateByKey(
|
||||
const std::string& key,
|
||||
const CameraFramePlan& plan,
|
||||
const DirectionalShadowSurfaceAllocation& shadowAllocation,
|
||||
DirectionalShadowExecutionState& shadowState) {
|
||||
if (key.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
EnsureBuiltinDirectionalShadowExecutionPolicyRegistryInitialized();
|
||||
|
||||
std::lock_guard<std::mutex> lock(
|
||||
GetDirectionalShadowExecutionPolicyRegistryMutex());
|
||||
const DirectionalShadowExecutionPolicyRegistry& registry =
|
||||
GetDirectionalShadowExecutionPolicyRegistry();
|
||||
const auto it = registry.find(key);
|
||||
if (it == registry.end() || !it->second) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return it->second(
|
||||
plan,
|
||||
shadowAllocation,
|
||||
shadowState);
|
||||
}
|
||||
|
||||
std::shared_ptr<const RenderPipelineAsset> ResolveRenderPipelineAssetOrDefault(
|
||||
std::shared_ptr<const RenderPipelineAsset> preferredAsset) {
|
||||
if (preferredAsset != nullptr) {
|
||||
@@ -567,7 +146,14 @@ std::unique_ptr<SceneDrawBackend> CreateSceneDrawBackendFromAsset(
|
||||
}
|
||||
|
||||
std::unique_ptr<SceneDrawBackend> CreateDefaultSceneDrawBackend() {
|
||||
return std::make_unique<Pipelines::BuiltinForwardPipeline>();
|
||||
if (std::unique_ptr<SceneDrawBackend> sceneDrawBackend =
|
||||
TryCreateSceneDrawBackendFromAsset(
|
||||
CreateDefaultPipelineBackendAsset());
|
||||
sceneDrawBackend != nullptr) {
|
||||
return sceneDrawBackend;
|
||||
}
|
||||
|
||||
return Pipelines::Internal::CreateConfiguredBuiltinForwardPipeline();
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Rendering {
|
||||
@@ -10,63 +8,12 @@ namespace Rendering {
|
||||
class SceneDrawBackend;
|
||||
class RenderPipeline;
|
||||
class RenderPipelineAsset;
|
||||
class RenderPass;
|
||||
struct CameraFramePlan;
|
||||
struct FinalColorSettings;
|
||||
struct DirectionalShadowExecutionState;
|
||||
struct DirectionalShadowSurfaceAllocation;
|
||||
|
||||
namespace Internal {
|
||||
|
||||
using PipelineBackendAssetFactory =
|
||||
std::function<std::shared_ptr<const RenderPipelineAsset>()>;
|
||||
using CameraFrameStandalonePassFactory =
|
||||
std::function<std::unique_ptr<RenderPass>()>;
|
||||
using CameraFramePlanPolicy =
|
||||
std::function<void(
|
||||
CameraFramePlan&,
|
||||
const FinalColorSettings&)>;
|
||||
using DirectionalShadowExecutionPolicy =
|
||||
std::function<bool(
|
||||
const CameraFramePlan&,
|
||||
const DirectionalShadowSurfaceAllocation&,
|
||||
DirectionalShadowExecutionState&)>;
|
||||
|
||||
std::shared_ptr<const RenderPipelineAsset> CreateConfiguredRenderPipelineAsset();
|
||||
std::shared_ptr<const RenderPipelineAsset> CreateFallbackRenderPipelineAsset();
|
||||
bool RegisterPipelineBackendAssetFactory(
|
||||
const std::string& key,
|
||||
PipelineBackendAssetFactory factory);
|
||||
bool UnregisterPipelineBackendAssetFactory(const std::string& key);
|
||||
std::shared_ptr<const RenderPipelineAsset> CreateDefaultPipelineBackendAsset();
|
||||
std::shared_ptr<const RenderPipelineAsset> CreatePipelineBackendAssetByKey(
|
||||
const std::string& key);
|
||||
bool RegisterCameraFrameStandalonePassFactory(
|
||||
const std::string& key,
|
||||
CameraFrameStandalonePassFactory factory);
|
||||
bool UnregisterCameraFrameStandalonePassFactory(
|
||||
const std::string& key);
|
||||
std::unique_ptr<RenderPass> CreateCameraFrameStandalonePassByKey(
|
||||
const std::string& key);
|
||||
bool RegisterCameraFramePlanPolicy(
|
||||
const std::string& key,
|
||||
CameraFramePlanPolicy policy);
|
||||
bool UnregisterCameraFramePlanPolicy(
|
||||
const std::string& key);
|
||||
bool ApplyCameraFramePlanPolicyByKey(
|
||||
const std::string& key,
|
||||
CameraFramePlan& plan,
|
||||
const FinalColorSettings& defaultFinalColorSettings);
|
||||
bool RegisterDirectionalShadowExecutionPolicy(
|
||||
const std::string& key,
|
||||
DirectionalShadowExecutionPolicy policy);
|
||||
bool UnregisterDirectionalShadowExecutionPolicy(
|
||||
const std::string& key);
|
||||
bool ConfigureDirectionalShadowExecutionStateByKey(
|
||||
const std::string& key,
|
||||
const CameraFramePlan& plan,
|
||||
const DirectionalShadowSurfaceAllocation& shadowAllocation,
|
||||
DirectionalShadowExecutionState& shadowState);
|
||||
|
||||
std::shared_ptr<const RenderPipelineAsset> ResolveRenderPipelineAssetOrDefault(
|
||||
std::shared_ptr<const RenderPipelineAsset> preferredAsset);
|
||||
|
||||
@@ -2,10 +2,11 @@
|
||||
|
||||
#include "Core/Asset/ResourceManager.h"
|
||||
#include "Debug/Logger.h"
|
||||
#include <XCEngine/Rendering/RenderPassGraphContract.h>
|
||||
#include "Rendering/Builtin/BuiltinPassLayoutUtils.h"
|
||||
#include "Rendering/Internal/RenderSurfacePipelineUtils.h"
|
||||
#include "Rendering/Internal/ShaderVariantUtils.h"
|
||||
#include "Rendering/RenderSurface.h"
|
||||
#include <XCEngine/Rendering/RenderPassGraphContract.h>
|
||||
#include "Resources/BuiltinResources.h"
|
||||
#include "RHI/RHICommandList.h"
|
||||
#include "RHI/RHIDescriptorPool.h"
|
||||
@@ -16,7 +17,9 @@
|
||||
#include "RHI/RHIResourceView.h"
|
||||
#include "RHI/RHISampler.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Rendering {
|
||||
@@ -45,7 +48,8 @@ const Resources::ShaderPass* FindCompatiblePass(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const Resources::ShaderPass* colorScalePass = shader.FindPass("ColorScale");
|
||||
const Resources::ShaderPass* colorScalePass =
|
||||
shader.FindPass("ColorScale");
|
||||
if (colorScalePass != nullptr &&
|
||||
::XCEngine::Rendering::Internal::ShaderPassHasGraphicsVariants(
|
||||
shader,
|
||||
@@ -55,13 +59,87 @@ const Resources::ShaderPass* FindCompatiblePass(
|
||||
}
|
||||
|
||||
if (shader.GetPassCount() > 0 &&
|
||||
::XCEngine::Rendering::Internal::ShaderPassHasGraphicsVariants(shader, shader.GetPasses()[0].name, backend)) {
|
||||
::XCEngine::Rendering::Internal::ShaderPassHasGraphicsVariants(
|
||||
shader,
|
||||
shader.GetPasses()[0].name,
|
||||
backend)) {
|
||||
return &shader.GetPasses()[0];
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool UsesContiguousDescriptorSets(
|
||||
const BuiltinPassResourceBindingPlan& bindingPlan) {
|
||||
if (bindingPlan.bindings.Empty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<bool> usedSets(
|
||||
static_cast<size_t>(bindingPlan.maxSetIndex) + 1u,
|
||||
false);
|
||||
Core::uint32 minSet = UINT32_MAX;
|
||||
Core::uint32 maxSet = 0u;
|
||||
for (const BuiltinPassResourceBindingDesc& binding :
|
||||
bindingPlan.bindings) {
|
||||
usedSets[binding.location.set] = true;
|
||||
minSet = std::min(minSet, binding.location.set);
|
||||
maxSet = std::max(maxSet, binding.location.set);
|
||||
}
|
||||
|
||||
for (Core::uint32 setIndex = minSet;
|
||||
setIndex <= maxSet;
|
||||
++setIndex) {
|
||||
if (!usedSets[setIndex]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IsSupportedFullscreenBindingPlan(
|
||||
const BuiltinPassResourceBindingPlan& bindingPlan) {
|
||||
if (!UsesContiguousDescriptorSets(bindingPlan)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const BuiltinPassResourceBindingDesc& binding :
|
||||
bindingPlan.bindings) {
|
||||
switch (binding.semantic) {
|
||||
case BuiltinPassResourceSemantic::PassConstants:
|
||||
case BuiltinPassResourceSemantic::SourceColorTexture:
|
||||
case BuiltinPassResourceSemantic::MaterialTexture:
|
||||
case BuiltinPassResourceSemantic::LinearClampSampler:
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const RenderPassContext::TextureBindingView* FindTextureBindingView(
|
||||
const RenderPassContext& context,
|
||||
const BuiltinPassResourceBindingDesc& bindingDesc) {
|
||||
auto matchesName =
|
||||
[&bindingDesc](
|
||||
const RenderPassContext::TextureBindingView& bindingView) {
|
||||
return bindingView.resourceName ==
|
||||
bindingDesc.name;
|
||||
};
|
||||
|
||||
const auto it =
|
||||
std::find_if(
|
||||
context.textureBindings.begin(),
|
||||
context.textureBindings.end(),
|
||||
matchesName);
|
||||
return it != context.textureBindings.end()
|
||||
? &(*it)
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
RHI::GraphicsPipelineDesc CreatePipelineDesc(
|
||||
RHI::RHIType backendType,
|
||||
RHI::RHIPipelineLayout* pipelineLayout,
|
||||
@@ -70,34 +148,54 @@ RHI::GraphicsPipelineDesc CreatePipelineDesc(
|
||||
const RenderSurface& surface) {
|
||||
RHI::GraphicsPipelineDesc pipelineDesc = {};
|
||||
pipelineDesc.pipelineLayout = pipelineLayout;
|
||||
pipelineDesc.topologyType = static_cast<uint32_t>(RHI::PrimitiveTopologyType::Triangle);
|
||||
::XCEngine::Rendering::Internal::ApplySingleColorAttachmentPropertiesToGraphicsPipelineDesc(
|
||||
surface,
|
||||
pipelineDesc);
|
||||
pipelineDesc.depthStencilFormat = static_cast<uint32_t>(RHI::Format::Unknown);
|
||||
pipelineDesc.topologyType = static_cast<uint32_t>(
|
||||
RHI::PrimitiveTopologyType::Triangle);
|
||||
::XCEngine::Rendering::Internal::
|
||||
ApplySingleColorAttachmentPropertiesToGraphicsPipelineDesc(
|
||||
surface,
|
||||
pipelineDesc);
|
||||
pipelineDesc.depthStencilFormat = static_cast<uint32_t>(
|
||||
RHI::Format::Unknown);
|
||||
|
||||
pipelineDesc.rasterizerState.fillMode = static_cast<uint32_t>(RHI::FillMode::Solid);
|
||||
pipelineDesc.rasterizerState.cullMode = static_cast<uint32_t>(RHI::CullMode::None);
|
||||
pipelineDesc.rasterizerState.frontFace = static_cast<uint32_t>(RHI::FrontFace::CounterClockwise);
|
||||
pipelineDesc.rasterizerState.fillMode = static_cast<uint32_t>(
|
||||
RHI::FillMode::Solid);
|
||||
pipelineDesc.rasterizerState.cullMode = static_cast<uint32_t>(
|
||||
RHI::CullMode::None);
|
||||
pipelineDesc.rasterizerState.frontFace =
|
||||
static_cast<uint32_t>(RHI::FrontFace::CounterClockwise);
|
||||
pipelineDesc.rasterizerState.depthClipEnable = true;
|
||||
|
||||
pipelineDesc.blendState.blendEnable = false;
|
||||
pipelineDesc.blendState.srcBlend = static_cast<uint32_t>(RHI::BlendFactor::One);
|
||||
pipelineDesc.blendState.dstBlend = static_cast<uint32_t>(RHI::BlendFactor::Zero);
|
||||
pipelineDesc.blendState.srcBlendAlpha = static_cast<uint32_t>(RHI::BlendFactor::One);
|
||||
pipelineDesc.blendState.dstBlendAlpha = static_cast<uint32_t>(RHI::BlendFactor::Zero);
|
||||
pipelineDesc.blendState.blendOp = static_cast<uint32_t>(RHI::BlendOp::Add);
|
||||
pipelineDesc.blendState.blendOpAlpha = static_cast<uint32_t>(RHI::BlendOp::Add);
|
||||
pipelineDesc.blendState.colorWriteMask = static_cast<uint8_t>(RHI::ColorWriteMask::All);
|
||||
pipelineDesc.blendState.srcBlend = static_cast<uint32_t>(
|
||||
RHI::BlendFactor::One);
|
||||
pipelineDesc.blendState.dstBlend = static_cast<uint32_t>(
|
||||
RHI::BlendFactor::Zero);
|
||||
pipelineDesc.blendState.srcBlendAlpha =
|
||||
static_cast<uint32_t>(RHI::BlendFactor::One);
|
||||
pipelineDesc.blendState.dstBlendAlpha =
|
||||
static_cast<uint32_t>(RHI::BlendFactor::Zero);
|
||||
pipelineDesc.blendState.blendOp = static_cast<uint32_t>(
|
||||
RHI::BlendOp::Add);
|
||||
pipelineDesc.blendState.blendOpAlpha = static_cast<uint32_t>(
|
||||
RHI::BlendOp::Add);
|
||||
pipelineDesc.blendState.colorWriteMask =
|
||||
static_cast<uint8_t>(RHI::ColorWriteMask::All);
|
||||
|
||||
pipelineDesc.depthStencilState.depthTestEnable = false;
|
||||
pipelineDesc.depthStencilState.depthWriteEnable = false;
|
||||
pipelineDesc.depthStencilState.depthFunc = static_cast<uint32_t>(RHI::ComparisonFunc::Always);
|
||||
pipelineDesc.depthStencilState.depthFunc = static_cast<uint32_t>(
|
||||
RHI::ComparisonFunc::Always);
|
||||
|
||||
const Resources::ShaderPass* shaderPass = shader.FindPass(passName);
|
||||
const Resources::ShaderBackend backend = ::XCEngine::Rendering::Internal::ToShaderBackend(backendType);
|
||||
const Resources::ShaderPass* shaderPass =
|
||||
shader.FindPass(passName);
|
||||
const Resources::ShaderBackend backend =
|
||||
::XCEngine::Rendering::Internal::ToShaderBackend(
|
||||
backendType);
|
||||
if (const Resources::ShaderStageVariant* vertexVariant =
|
||||
shader.FindVariant(passName, Resources::ShaderType::Vertex, backend)) {
|
||||
shader.FindVariant(
|
||||
passName,
|
||||
Resources::ShaderType::Vertex,
|
||||
backend)) {
|
||||
if (shaderPass != nullptr) {
|
||||
::XCEngine::Rendering::Internal::ApplyShaderStageVariant(
|
||||
shader.GetPath(),
|
||||
@@ -108,7 +206,10 @@ RHI::GraphicsPipelineDesc CreatePipelineDesc(
|
||||
}
|
||||
}
|
||||
if (const Resources::ShaderStageVariant* fragmentVariant =
|
||||
shader.FindVariant(passName, Resources::ShaderType::Fragment, backend)) {
|
||||
shader.FindVariant(
|
||||
passName,
|
||||
Resources::ShaderType::Fragment,
|
||||
backend)) {
|
||||
if (shaderPass != nullptr) {
|
||||
::XCEngine::Rendering::Internal::ApplyShaderStageVariant(
|
||||
shader.GetPath(),
|
||||
@@ -132,7 +233,8 @@ BuiltinVectorFullscreenPass::BuiltinVectorFullscreenPass(
|
||||
, m_preferredPassName(std::move(preferredPassName))
|
||||
, m_vectorPayload(vectorPayload) {
|
||||
if (m_shaderPath.Empty()) {
|
||||
m_shaderPath = Resources::GetBuiltinColorScalePostProcessShaderPath();
|
||||
m_shaderPath =
|
||||
Resources::GetBuiltinColorScalePostProcessShaderPath();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,44 +257,56 @@ bool BuiltinVectorFullscreenPass::RecordRenderGraph(
|
||||
context);
|
||||
}
|
||||
|
||||
bool BuiltinVectorFullscreenPass::Execute(const RenderPassContext& context) {
|
||||
bool BuiltinVectorFullscreenPass::Execute(
|
||||
const RenderPassContext& context) {
|
||||
if (!context.renderContext.IsValid() ||
|
||||
context.sourceSurface == nullptr ||
|
||||
context.sourceColorView == nullptr) {
|
||||
return false;
|
||||
}
|
||||
if (!::XCEngine::Rendering::Internal::HasSingleColorAttachment(*context.sourceSurface)) {
|
||||
!::XCEngine::Rendering::Internal::HasSingleColorAttachment(
|
||||
context.surface)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const std::vector<RHI::RHIResourceView*>& colorAttachments = context.surface.GetColorAttachments();
|
||||
if (!::XCEngine::Rendering::Internal::HasSingleColorAttachment(context.surface) ||
|
||||
colorAttachments.empty() ||
|
||||
const std::vector<RHI::RHIResourceView*>& colorAttachments =
|
||||
context.surface.GetColorAttachments();
|
||||
if (colorAttachments.empty() ||
|
||||
colorAttachments[0] == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const Math::RectInt renderArea = context.surface.GetRenderArea();
|
||||
if (renderArea.width <= 0 || renderArea.height <= 0) {
|
||||
const Math::RectInt renderArea =
|
||||
context.surface.GetRenderArea();
|
||||
if (renderArea.width <= 0 ||
|
||||
renderArea.height <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!EnsureInitialized(context.renderContext, context.surface)) {
|
||||
if (!EnsureInitialized(
|
||||
context.renderContext,
|
||||
context.surface)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
PostProcessConstants constants = {};
|
||||
constants.vectorPayload = m_vectorPayload;
|
||||
m_constantsSet.set->WriteConstant(0, &constants, sizeof(constants));
|
||||
|
||||
if (m_boundSourceColorView != context.sourceColorView) {
|
||||
m_textureSet.set->Update(0, context.sourceColorView);
|
||||
m_boundSourceColorView = context.sourceColorView;
|
||||
if (m_passLayout.sourceColorTexture.IsValid() &&
|
||||
(context.sourceSurface == nullptr ||
|
||||
context.sourceColorView == nullptr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RHI::RHICommandList* commandList = context.renderContext.commandList;
|
||||
RHI::RHIResourceView* renderTarget = colorAttachments[0];
|
||||
const bool autoTransitionSource = context.sourceSurface->IsAutoTransitionEnabled();
|
||||
if (!UpdateDescriptorSets(context)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RHI::RHICommandList* commandList =
|
||||
context.renderContext.commandList;
|
||||
if (commandList == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RHI::RHIResourceView* renderTarget =
|
||||
colorAttachments[0];
|
||||
const bool autoTransitionSource =
|
||||
m_passLayout.sourceColorTexture.IsValid() &&
|
||||
context.sourceSurface != nullptr &&
|
||||
context.sourceSurface->IsAutoTransitionEnabled();
|
||||
|
||||
if (context.surface.IsAutoTransitionEnabled()) {
|
||||
commandList->TransitionBarrier(
|
||||
@@ -200,13 +314,16 @@ bool BuiltinVectorFullscreenPass::Execute(const RenderPassContext& context) {
|
||||
context.surface.GetColorStateBefore(),
|
||||
RHI::ResourceStates::RenderTarget);
|
||||
}
|
||||
if (autoTransitionSource) {
|
||||
commandList->TransitionBarrier(
|
||||
context.sourceColorView,
|
||||
context.sourceColorState,
|
||||
RHI::ResourceStates::PixelShaderResource);
|
||||
} else if (context.sourceColorState != RHI::ResourceStates::PixelShaderResource) {
|
||||
return false;
|
||||
if (m_passLayout.sourceColorTexture.IsValid()) {
|
||||
if (autoTransitionSource) {
|
||||
commandList->TransitionBarrier(
|
||||
context.sourceColorView,
|
||||
context.sourceColorState,
|
||||
RHI::ResourceStates::PixelShaderResource);
|
||||
} else if (context.sourceColorState !=
|
||||
RHI::ResourceStates::PixelShaderResource) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
commandList->SetRenderTargets(1, &renderTarget, nullptr);
|
||||
@@ -228,15 +345,38 @@ bool BuiltinVectorFullscreenPass::Execute(const RenderPassContext& context) {
|
||||
|
||||
commandList->SetViewport(viewport);
|
||||
commandList->SetScissorRect(scissorRect);
|
||||
commandList->SetPrimitiveTopology(RHI::PrimitiveTopology::TriangleList);
|
||||
commandList->SetPrimitiveTopology(
|
||||
RHI::PrimitiveTopology::TriangleList);
|
||||
commandList->SetPipelineState(m_pipelineState);
|
||||
|
||||
RHI::RHIDescriptorSet* descriptorSets[] = {
|
||||
m_constantsSet.set,
|
||||
m_textureSet.set,
|
||||
m_samplerSet.set
|
||||
};
|
||||
commandList->SetGraphicsDescriptorSets(0, 3, descriptorSets, m_pipelineLayout);
|
||||
if (m_passLayout.descriptorSetCount > 0u) {
|
||||
std::vector<RHI::RHIDescriptorSet*> descriptorSets(
|
||||
m_passLayout.descriptorSetCount,
|
||||
nullptr);
|
||||
for (Core::uint32 descriptorOffset = 0u;
|
||||
descriptorOffset < m_passLayout.descriptorSetCount;
|
||||
++descriptorOffset) {
|
||||
const Core::uint32 setIndex =
|
||||
m_passLayout.firstDescriptorSet +
|
||||
descriptorOffset;
|
||||
if (setIndex >=
|
||||
m_passLayout.descriptorSets.size() ||
|
||||
m_passLayout.descriptorSets[setIndex].set ==
|
||||
nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
descriptorSets[descriptorOffset] =
|
||||
m_passLayout.descriptorSets[setIndex].set;
|
||||
}
|
||||
|
||||
commandList->SetGraphicsDescriptorSets(
|
||||
m_passLayout.firstDescriptorSet,
|
||||
m_passLayout.descriptorSetCount,
|
||||
descriptorSets.data(),
|
||||
m_passLayout.pipelineLayout);
|
||||
}
|
||||
|
||||
commandList->Draw(3, 1, 0, 0);
|
||||
commandList->EndRenderPass();
|
||||
|
||||
@@ -246,7 +386,8 @@ bool BuiltinVectorFullscreenPass::Execute(const RenderPassContext& context) {
|
||||
RHI::ResourceStates::RenderTarget,
|
||||
context.surface.GetColorStateAfter());
|
||||
}
|
||||
if (autoTransitionSource) {
|
||||
if (m_passLayout.sourceColorTexture.IsValid() &&
|
||||
autoTransitionSource) {
|
||||
commandList->TransitionBarrier(
|
||||
context.sourceColorView,
|
||||
RHI::ResourceStates::PixelShaderResource,
|
||||
@@ -260,7 +401,8 @@ void BuiltinVectorFullscreenPass::Shutdown() {
|
||||
DestroyResources();
|
||||
}
|
||||
|
||||
void BuiltinVectorFullscreenPass::SetVectorPayload(const Math::Vector4& vectorPayload) {
|
||||
void BuiltinVectorFullscreenPass::SetVectorPayload(
|
||||
const Math::Vector4& vectorPayload) {
|
||||
m_vectorPayload = vectorPayload;
|
||||
}
|
||||
|
||||
@@ -268,7 +410,8 @@ const Math::Vector4& BuiltinVectorFullscreenPass::GetVectorPayload() const {
|
||||
return m_vectorPayload;
|
||||
}
|
||||
|
||||
void BuiltinVectorFullscreenPass::SetShaderPath(const Containers::String& shaderPath) {
|
||||
void BuiltinVectorFullscreenPass::SetShaderPath(
|
||||
const Containers::String& shaderPath) {
|
||||
if (m_shaderPath == shaderPath) {
|
||||
return;
|
||||
}
|
||||
@@ -291,7 +434,8 @@ void BuiltinVectorFullscreenPass::SetPreferredPassName(
|
||||
m_preferredPassName = preferredPassName;
|
||||
}
|
||||
|
||||
const Containers::String& BuiltinVectorFullscreenPass::GetPreferredPassName() const {
|
||||
const Containers::String&
|
||||
BuiltinVectorFullscreenPass::GetPreferredPassName() const {
|
||||
return m_preferredPassName;
|
||||
}
|
||||
|
||||
@@ -299,22 +443,25 @@ bool BuiltinVectorFullscreenPass::EnsureInitialized(
|
||||
const RenderContext& renderContext,
|
||||
const RenderSurface& surface) {
|
||||
const RHI::Format renderTargetFormat =
|
||||
::XCEngine::Rendering::Internal::ResolveSurfaceColorFormat(surface, 0u);
|
||||
::XCEngine::Rendering::Internal::ResolveSurfaceColorFormat(
|
||||
surface,
|
||||
0u);
|
||||
const uint32_t renderTargetSampleCount =
|
||||
::XCEngine::Rendering::Internal::ResolveSurfaceSampleCount(surface);
|
||||
::XCEngine::Rendering::Internal::ResolveSurfaceSampleCount(
|
||||
surface);
|
||||
const uint32_t renderTargetSampleQuality =
|
||||
::XCEngine::Rendering::Internal::ResolveSurfaceSampleQuality(surface);
|
||||
::XCEngine::Rendering::Internal::ResolveSurfaceSampleQuality(
|
||||
surface);
|
||||
if (m_device == renderContext.device &&
|
||||
m_backendType == renderContext.backendType &&
|
||||
m_renderTargetFormat == renderTargetFormat &&
|
||||
m_renderTargetSampleCount == renderTargetSampleCount &&
|
||||
m_renderTargetSampleQuality == renderTargetSampleQuality &&
|
||||
m_pipelineLayout != nullptr &&
|
||||
m_renderTargetSampleCount ==
|
||||
renderTargetSampleCount &&
|
||||
m_renderTargetSampleQuality ==
|
||||
renderTargetSampleQuality &&
|
||||
m_passLayout.pipelineLayout != nullptr &&
|
||||
m_pipelineState != nullptr &&
|
||||
m_sampler != nullptr &&
|
||||
m_constantsSet.set != nullptr &&
|
||||
m_textureSet.set != nullptr &&
|
||||
m_samplerSet.set != nullptr) {
|
||||
m_sampler != nullptr) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -330,38 +477,98 @@ bool BuiltinVectorFullscreenPass::CreateResources(
|
||||
}
|
||||
|
||||
RHI::Format renderTargetFormat = RHI::Format::Unknown;
|
||||
if (!::XCEngine::Rendering::Internal::TryResolveSingleColorAttachmentFormat(surface, renderTargetFormat)) {
|
||||
if (!::XCEngine::Rendering::Internal::
|
||||
TryResolveSingleColorAttachmentFormat(
|
||||
surface,
|
||||
renderTargetFormat)) {
|
||||
Debug::Logger::Get().Error(
|
||||
Debug::LogCategory::Rendering,
|
||||
"BuiltinVectorFullscreenPass requires exactly one valid destination color attachment");
|
||||
"BuiltinVectorFullscreenPass requires exactly one "
|
||||
"valid destination color attachment");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_shaderPath.Empty()) {
|
||||
Debug::Logger::Get().Error(
|
||||
Debug::LogCategory::Rendering,
|
||||
"BuiltinVectorFullscreenPass requires a shader path before resource creation");
|
||||
"BuiltinVectorFullscreenPass requires a shader path "
|
||||
"before resource creation");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_shader = Resources::ResourceManager::Get().Load<Resources::Shader>(m_shaderPath);
|
||||
m_shader =
|
||||
Resources::ResourceManager::Get().Load<Resources::Shader>(
|
||||
m_shaderPath);
|
||||
if (!m_shader.IsValid()) {
|
||||
Debug::Logger::Get().Error(
|
||||
Debug::LogCategory::Rendering,
|
||||
"BuiltinVectorFullscreenPass failed to load configured fullscreen shader resource");
|
||||
"BuiltinVectorFullscreenPass failed to load "
|
||||
"configured fullscreen shader resource");
|
||||
DestroyResources();
|
||||
return false;
|
||||
}
|
||||
|
||||
const Resources::ShaderBackend backend = ::XCEngine::Rendering::Internal::ToShaderBackend(renderContext.backendType);
|
||||
const Resources::ShaderBackend backend =
|
||||
::XCEngine::Rendering::Internal::ToShaderBackend(
|
||||
renderContext.backendType);
|
||||
const Resources::ShaderPass* selectedPass =
|
||||
FindCompatiblePass(*m_shader.Get(), backend, m_preferredPassName);
|
||||
FindCompatiblePass(
|
||||
*m_shader.Get(),
|
||||
backend,
|
||||
m_preferredPassName);
|
||||
if (selectedPass == nullptr) {
|
||||
Debug::Logger::Get().Error(
|
||||
Debug::LogCategory::Rendering,
|
||||
m_preferredPassName.Empty()
|
||||
? "BuiltinVectorFullscreenPass could not resolve a compatible fullscreen shader pass"
|
||||
: "BuiltinVectorFullscreenPass could not resolve the configured fullscreen shader pass");
|
||||
? "BuiltinVectorFullscreenPass could not resolve "
|
||||
"a compatible fullscreen shader pass"
|
||||
: "BuiltinVectorFullscreenPass could not resolve "
|
||||
"the configured fullscreen shader pass");
|
||||
DestroyResources();
|
||||
return false;
|
||||
}
|
||||
|
||||
BuiltinPassResourceBindingPlan bindingPlan = {};
|
||||
Containers::String bindingPlanError;
|
||||
if (!TryBuildBuiltinPassResourceBindingPlan(
|
||||
*selectedPass,
|
||||
bindingPlan,
|
||||
&bindingPlanError)) {
|
||||
Debug::Logger::Get().Error(
|
||||
Debug::LogCategory::Rendering,
|
||||
(Containers::String(
|
||||
"BuiltinVectorFullscreenPass failed to "
|
||||
"resolve shader resource bindings: ") +
|
||||
bindingPlanError)
|
||||
.CStr());
|
||||
DestroyResources();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!IsSupportedFullscreenBindingPlan(bindingPlan)) {
|
||||
Debug::Logger::Get().Error(
|
||||
Debug::LogCategory::Rendering,
|
||||
"BuiltinVectorFullscreenPass only supports "
|
||||
"PassConstants, SourceColorTexture, "
|
||||
"MaterialTexture, and LinearClampSampler "
|
||||
"resource semantics");
|
||||
DestroyResources();
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<BuiltinPassSetLayoutMetadata> setLayouts;
|
||||
Containers::String setLayoutError;
|
||||
if (!TryBuildBuiltinPassSetLayouts(
|
||||
bindingPlan,
|
||||
setLayouts,
|
||||
&setLayoutError)) {
|
||||
Debug::Logger::Get().Error(
|
||||
Debug::LogCategory::Rendering,
|
||||
(Containers::String(
|
||||
"BuiltinVectorFullscreenPass failed to build "
|
||||
"descriptor set layouts: ") +
|
||||
setLayoutError)
|
||||
.CStr());
|
||||
DestroyResources();
|
||||
return false;
|
||||
}
|
||||
@@ -369,62 +576,64 @@ bool BuiltinVectorFullscreenPass::CreateResources(
|
||||
m_device = renderContext.device;
|
||||
m_backendType = renderContext.backendType;
|
||||
m_renderTargetFormat = renderTargetFormat;
|
||||
m_renderTargetSampleCount = ::XCEngine::Rendering::Internal::ResolveSurfaceSampleCount(surface);
|
||||
m_renderTargetSampleQuality = ::XCEngine::Rendering::Internal::ResolveSurfaceSampleQuality(surface);
|
||||
m_renderTargetSampleCount =
|
||||
::XCEngine::Rendering::Internal::ResolveSurfaceSampleCount(
|
||||
surface);
|
||||
m_renderTargetSampleQuality =
|
||||
::XCEngine::Rendering::Internal::
|
||||
ResolveSurfaceSampleQuality(surface);
|
||||
|
||||
RHI::DescriptorSetLayoutBinding constantBinding = {};
|
||||
constantBinding.binding = 0;
|
||||
constantBinding.type = static_cast<uint32_t>(RHI::DescriptorType::CBV);
|
||||
constantBinding.count = 1;
|
||||
constantBinding.visibility = static_cast<uint32_t>(RHI::ShaderVisibility::All);
|
||||
m_passLayout.setLayouts = std::move(setLayouts);
|
||||
m_passLayout.descriptorSets.resize(
|
||||
m_passLayout.setLayouts.size());
|
||||
m_passLayout.boundSetStates.resize(
|
||||
m_passLayout.setLayouts.size());
|
||||
m_passLayout.passConstants = bindingPlan.passConstants;
|
||||
m_passLayout.sourceColorTexture =
|
||||
bindingPlan.sourceColorTexture;
|
||||
m_passLayout.linearClampSampler =
|
||||
bindingPlan.linearClampSampler;
|
||||
m_passLayout.firstDescriptorSet =
|
||||
bindingPlan.firstDescriptorSet;
|
||||
m_passLayout.descriptorSetCount =
|
||||
bindingPlan.descriptorSetCount;
|
||||
|
||||
RHI::DescriptorSetLayoutBinding textureBinding = {};
|
||||
textureBinding.binding = 0;
|
||||
textureBinding.type = static_cast<uint32_t>(RHI::DescriptorType::SRV);
|
||||
textureBinding.count = 1;
|
||||
textureBinding.visibility = static_cast<uint32_t>(RHI::ShaderVisibility::All);
|
||||
|
||||
RHI::DescriptorSetLayoutBinding samplerBinding = {};
|
||||
samplerBinding.binding = 0;
|
||||
samplerBinding.type = static_cast<uint32_t>(RHI::DescriptorType::Sampler);
|
||||
samplerBinding.count = 1;
|
||||
samplerBinding.visibility = static_cast<uint32_t>(RHI::ShaderVisibility::All);
|
||||
|
||||
RHI::DescriptorSetLayoutDesc constantLayout = {};
|
||||
constantLayout.bindings = &constantBinding;
|
||||
constantLayout.bindingCount = 1;
|
||||
|
||||
RHI::DescriptorSetLayoutDesc textureLayout = {};
|
||||
textureLayout.bindings = &textureBinding;
|
||||
textureLayout.bindingCount = 1;
|
||||
|
||||
RHI::DescriptorSetLayoutDesc samplerLayout = {};
|
||||
samplerLayout.bindings = &samplerBinding;
|
||||
samplerLayout.bindingCount = 1;
|
||||
|
||||
RHI::DescriptorSetLayoutDesc setLayouts[] = {
|
||||
constantLayout,
|
||||
textureLayout,
|
||||
samplerLayout
|
||||
};
|
||||
std::vector<RHI::DescriptorSetLayoutDesc> nativeSetLayouts(
|
||||
m_passLayout.setLayouts.size());
|
||||
for (size_t setIndex = 0u;
|
||||
setIndex < m_passLayout.setLayouts.size();
|
||||
++setIndex) {
|
||||
nativeSetLayouts[setIndex] =
|
||||
m_passLayout.setLayouts[setIndex].layout;
|
||||
}
|
||||
|
||||
RHI::RHIPipelineLayoutDesc pipelineLayoutDesc = {};
|
||||
pipelineLayoutDesc.setLayouts = setLayouts;
|
||||
pipelineLayoutDesc.setLayoutCount = 3;
|
||||
m_pipelineLayout = m_device->CreatePipelineLayout(pipelineLayoutDesc);
|
||||
if (m_pipelineLayout == nullptr) {
|
||||
pipelineLayoutDesc.setLayouts =
|
||||
nativeSetLayouts.empty()
|
||||
? nullptr
|
||||
: nativeSetLayouts.data();
|
||||
pipelineLayoutDesc.setLayoutCount =
|
||||
static_cast<uint32_t>(nativeSetLayouts.size());
|
||||
m_passLayout.pipelineLayout =
|
||||
m_device->CreatePipelineLayout(pipelineLayoutDesc);
|
||||
if (m_passLayout.pipelineLayout == nullptr) {
|
||||
DestroyResources();
|
||||
return false;
|
||||
}
|
||||
|
||||
RHI::SamplerDesc samplerDesc = {};
|
||||
samplerDesc.filter = static_cast<uint32_t>(RHI::FilterMode::Linear);
|
||||
samplerDesc.addressU = static_cast<uint32_t>(RHI::TextureAddressMode::Clamp);
|
||||
samplerDesc.addressV = static_cast<uint32_t>(RHI::TextureAddressMode::Clamp);
|
||||
samplerDesc.addressW = static_cast<uint32_t>(RHI::TextureAddressMode::Clamp);
|
||||
samplerDesc.filter =
|
||||
static_cast<uint32_t>(RHI::FilterMode::Linear);
|
||||
samplerDesc.addressU = static_cast<uint32_t>(
|
||||
RHI::TextureAddressMode::Clamp);
|
||||
samplerDesc.addressV = static_cast<uint32_t>(
|
||||
RHI::TextureAddressMode::Clamp);
|
||||
samplerDesc.addressW = static_cast<uint32_t>(
|
||||
RHI::TextureAddressMode::Clamp);
|
||||
samplerDesc.mipLodBias = 0.0f;
|
||||
samplerDesc.maxAnisotropy = 1;
|
||||
samplerDesc.comparisonFunc = static_cast<uint32_t>(RHI::ComparisonFunc::Always);
|
||||
samplerDesc.comparisonFunc = static_cast<uint32_t>(
|
||||
RHI::ComparisonFunc::Always);
|
||||
samplerDesc.minLod = 0.0f;
|
||||
samplerDesc.maxLod = 1000.0f;
|
||||
m_sampler = m_device->CreateSampler(samplerDesc);
|
||||
@@ -433,58 +642,47 @@ bool BuiltinVectorFullscreenPass::CreateResources(
|
||||
return false;
|
||||
}
|
||||
|
||||
auto createOwnedDescriptorSet =
|
||||
[this](const RHI::DescriptorSetLayoutDesc& layout,
|
||||
RHI::DescriptorHeapType heapType,
|
||||
bool shaderVisible,
|
||||
OwnedDescriptorSet& ownedSet) -> bool {
|
||||
RHI::DescriptorPoolDesc poolDesc = {};
|
||||
poolDesc.type = heapType;
|
||||
poolDesc.descriptorCount = 1;
|
||||
poolDesc.shaderVisible = shaderVisible;
|
||||
ownedSet.pool = m_device->CreateDescriptorPool(poolDesc);
|
||||
if (ownedSet.pool == nullptr) {
|
||||
for (size_t setIndex = 0u;
|
||||
setIndex < m_passLayout.setLayouts.size();
|
||||
++setIndex) {
|
||||
const BuiltinPassSetLayoutMetadata& setLayout =
|
||||
m_passLayout.setLayouts[setIndex];
|
||||
if (setLayout.bindings.empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!CreateOwnedDescriptorSet(
|
||||
setLayout,
|
||||
m_passLayout.descriptorSets[setIndex])) {
|
||||
DestroyResources();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (setLayout.usesSampler) {
|
||||
if (!setLayout.usesLinearClampSampler ||
|
||||
!m_passLayout.linearClampSampler.IsValid() ||
|
||||
m_passLayout.linearClampSampler.set !=
|
||||
setIndex) {
|
||||
DestroyResources();
|
||||
return false;
|
||||
}
|
||||
|
||||
ownedSet.set = ownedSet.pool->AllocateSet(layout);
|
||||
if (ownedSet.set == nullptr) {
|
||||
DestroyOwnedDescriptorSet(ownedSet);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
if (!createOwnedDescriptorSet(
|
||||
constantLayout,
|
||||
RHI::DescriptorHeapType::CBV_SRV_UAV,
|
||||
false,
|
||||
m_constantsSet) ||
|
||||
!createOwnedDescriptorSet(
|
||||
textureLayout,
|
||||
RHI::DescriptorHeapType::CBV_SRV_UAV,
|
||||
true,
|
||||
m_textureSet) ||
|
||||
!createOwnedDescriptorSet(
|
||||
samplerLayout,
|
||||
RHI::DescriptorHeapType::Sampler,
|
||||
true,
|
||||
m_samplerSet)) {
|
||||
DestroyResources();
|
||||
return false;
|
||||
m_passLayout.descriptorSets[setIndex]
|
||||
.set->UpdateSampler(
|
||||
m_passLayout.linearClampSampler.binding,
|
||||
m_sampler);
|
||||
}
|
||||
}
|
||||
|
||||
m_samplerSet.set->UpdateSampler(0, m_sampler);
|
||||
|
||||
m_pipelineState = m_device->CreatePipelineState(
|
||||
CreatePipelineDesc(
|
||||
m_backendType,
|
||||
m_pipelineLayout,
|
||||
m_passLayout.pipelineLayout,
|
||||
*m_shader.Get(),
|
||||
selectedPass->name,
|
||||
surface));
|
||||
if (m_pipelineState == nullptr || !m_pipelineState->IsValid()) {
|
||||
if (m_pipelineState == nullptr ||
|
||||
!m_pipelineState->IsValid()) {
|
||||
DestroyResources();
|
||||
return false;
|
||||
}
|
||||
@@ -492,24 +690,149 @@ bool BuiltinVectorFullscreenPass::CreateResources(
|
||||
return true;
|
||||
}
|
||||
|
||||
void BuiltinVectorFullscreenPass::DestroyResources() {
|
||||
m_boundSourceColorView = nullptr;
|
||||
bool BuiltinVectorFullscreenPass::CreateOwnedDescriptorSet(
|
||||
const BuiltinPassSetLayoutMetadata& setLayout,
|
||||
OwnedDescriptorSet& descriptorSet) {
|
||||
RHI::DescriptorPoolDesc poolDesc = {};
|
||||
poolDesc.type = setLayout.heapType;
|
||||
poolDesc.descriptorCount =
|
||||
CountBuiltinPassHeapDescriptors(
|
||||
setLayout.heapType,
|
||||
setLayout.bindings);
|
||||
poolDesc.shaderVisible = setLayout.shaderVisible;
|
||||
|
||||
descriptorSet.pool =
|
||||
m_device->CreateDescriptorPool(poolDesc);
|
||||
if (descriptorSet.pool == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
descriptorSet.set =
|
||||
descriptorSet.pool->AllocateSet(setLayout.layout);
|
||||
if (descriptorSet.set == nullptr) {
|
||||
DestroyOwnedDescriptorSet(descriptorSet);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BuiltinVectorFullscreenPass::UpdateDescriptorSets(
|
||||
const RenderPassContext& context) {
|
||||
for (size_t setIndex = 0u;
|
||||
setIndex < m_passLayout.setLayouts.size();
|
||||
++setIndex) {
|
||||
const BuiltinPassSetLayoutMetadata& setLayout =
|
||||
m_passLayout.setLayouts[setIndex];
|
||||
if (setLayout.bindings.empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
OwnedDescriptorSet& descriptorSet =
|
||||
m_passLayout.descriptorSets[setIndex];
|
||||
BoundSetState& boundSetState =
|
||||
m_passLayout.boundSetStates[setIndex];
|
||||
if (descriptorSet.set == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (setLayout.usesPassConstants) {
|
||||
if (!m_passLayout.passConstants.IsValid() ||
|
||||
m_passLayout.passConstants.set != setIndex) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const PostProcessConstants constants = {
|
||||
m_vectorPayload
|
||||
};
|
||||
descriptorSet.set->WriteConstant(
|
||||
m_passLayout.passConstants.binding,
|
||||
&constants,
|
||||
sizeof(constants));
|
||||
}
|
||||
|
||||
if (setLayout.usesSourceColorTexture) {
|
||||
if (context.sourceColorView == nullptr ||
|
||||
!m_passLayout.sourceColorTexture.IsValid() ||
|
||||
m_passLayout.sourceColorTexture.set !=
|
||||
setIndex) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (boundSetState.sourceColorTextureView !=
|
||||
context.sourceColorView) {
|
||||
descriptorSet.set->Update(
|
||||
m_passLayout.sourceColorTexture.binding,
|
||||
context.sourceColorView);
|
||||
boundSetState.sourceColorTextureView =
|
||||
context.sourceColorView;
|
||||
}
|
||||
}
|
||||
|
||||
if (setLayout.usesMaterialTextures) {
|
||||
if (boundSetState.materialTextureViews.size() !=
|
||||
setLayout.materialTextureBindings.size()) {
|
||||
boundSetState.materialTextureViews.assign(
|
||||
setLayout.materialTextureBindings.size(),
|
||||
nullptr);
|
||||
}
|
||||
|
||||
for (size_t bindingIndex = 0u;
|
||||
bindingIndex <
|
||||
setLayout.materialTextureBindings.size();
|
||||
++bindingIndex) {
|
||||
const BuiltinPassResourceBindingDesc&
|
||||
textureBinding =
|
||||
setLayout.materialTextureBindings
|
||||
[bindingIndex];
|
||||
RHI::RHIResourceView* resolvedTextureView =
|
||||
ResolveExtraTextureView(
|
||||
context,
|
||||
textureBinding);
|
||||
if (resolvedTextureView == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (boundSetState.materialTextureViews
|
||||
[bindingIndex] !=
|
||||
resolvedTextureView) {
|
||||
descriptorSet.set->Update(
|
||||
textureBinding.location.binding,
|
||||
resolvedTextureView);
|
||||
boundSetState.materialTextureViews
|
||||
[bindingIndex] = resolvedTextureView;
|
||||
}
|
||||
}
|
||||
} else if (!boundSetState.materialTextureViews
|
||||
.empty()) {
|
||||
boundSetState.materialTextureViews.clear();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
RHI::RHIResourceView*
|
||||
BuiltinVectorFullscreenPass::ResolveExtraTextureView(
|
||||
const RenderPassContext& context,
|
||||
const BuiltinPassResourceBindingDesc& bindingDesc) const {
|
||||
const RenderPassContext::TextureBindingView* bindingView =
|
||||
FindTextureBindingView(
|
||||
context,
|
||||
bindingDesc);
|
||||
return bindingView != nullptr
|
||||
? bindingView->resourceView
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
void BuiltinVectorFullscreenPass::DestroyResources() {
|
||||
if (m_pipelineState != nullptr) {
|
||||
m_pipelineState->Shutdown();
|
||||
delete m_pipelineState;
|
||||
m_pipelineState = nullptr;
|
||||
}
|
||||
|
||||
DestroyOwnedDescriptorSet(m_samplerSet);
|
||||
DestroyOwnedDescriptorSet(m_textureSet);
|
||||
DestroyOwnedDescriptorSet(m_constantsSet);
|
||||
|
||||
if (m_pipelineLayout != nullptr) {
|
||||
m_pipelineLayout->Shutdown();
|
||||
delete m_pipelineLayout;
|
||||
m_pipelineLayout = nullptr;
|
||||
}
|
||||
DestroyPassResourceLayout();
|
||||
|
||||
if (m_sampler != nullptr) {
|
||||
m_sampler->Shutdown();
|
||||
@@ -525,7 +848,30 @@ void BuiltinVectorFullscreenPass::DestroyResources() {
|
||||
m_renderTargetSampleQuality = 0u;
|
||||
}
|
||||
|
||||
void BuiltinVectorFullscreenPass::DestroyOwnedDescriptorSet(OwnedDescriptorSet& descriptorSet) {
|
||||
void BuiltinVectorFullscreenPass::DestroyPassResourceLayout() {
|
||||
for (OwnedDescriptorSet& descriptorSet :
|
||||
m_passLayout.descriptorSets) {
|
||||
DestroyOwnedDescriptorSet(descriptorSet);
|
||||
}
|
||||
m_passLayout.descriptorSets.clear();
|
||||
m_passLayout.boundSetStates.clear();
|
||||
m_passLayout.setLayouts.clear();
|
||||
|
||||
if (m_passLayout.pipelineLayout != nullptr) {
|
||||
m_passLayout.pipelineLayout->Shutdown();
|
||||
delete m_passLayout.pipelineLayout;
|
||||
m_passLayout.pipelineLayout = nullptr;
|
||||
}
|
||||
|
||||
m_passLayout.passConstants = {};
|
||||
m_passLayout.sourceColorTexture = {};
|
||||
m_passLayout.linearClampSampler = {};
|
||||
m_passLayout.firstDescriptorSet = 0u;
|
||||
m_passLayout.descriptorSetCount = 0u;
|
||||
}
|
||||
|
||||
void BuiltinVectorFullscreenPass::DestroyOwnedDescriptorSet(
|
||||
OwnedDescriptorSet& descriptorSet) {
|
||||
if (descriptorSet.set != nullptr) {
|
||||
descriptorSet.set->Shutdown();
|
||||
delete descriptorSet.set;
|
||||
|
||||
@@ -6,9 +6,7 @@ namespace XCEngine {
|
||||
namespace Rendering {
|
||||
namespace Pipelines {
|
||||
|
||||
BuiltinForwardPipeline::BuiltinForwardPipeline() {
|
||||
Internal::RegisterBuiltinForwardSceneFeatures(m_forwardSceneFeatureHost);
|
||||
}
|
||||
BuiltinForwardPipeline::BuiltinForwardPipeline() = default;
|
||||
|
||||
BuiltinForwardPipeline::~BuiltinForwardPipeline() {
|
||||
Shutdown();
|
||||
@@ -28,7 +26,7 @@ SceneRenderFeaturePass* BuiltinForwardPipeline::GetForwardSceneFeaturePass(size_
|
||||
}
|
||||
|
||||
std::unique_ptr<RenderPipeline> BuiltinForwardPipelineAsset::CreatePipeline() const {
|
||||
return std::make_unique<BuiltinForwardPipeline>();
|
||||
return Internal::CreateConfiguredBuiltinForwardPipeline();
|
||||
}
|
||||
|
||||
} // namespace Pipelines
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
|
||||
#include "Rendering/Features/BuiltinGaussianSplatPass.h"
|
||||
#include "Rendering/Features/BuiltinVolumetricPass.h"
|
||||
#include "Rendering/SceneRenderFeatureHost.h"
|
||||
#include "Rendering/Passes/BuiltinDepthOnlyPass.h"
|
||||
#include "Rendering/Passes/BuiltinShadowCasterPass.h"
|
||||
#include "Rendering/Pipelines/BuiltinForwardPipeline.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
@@ -11,9 +13,35 @@ namespace Rendering {
|
||||
namespace Pipelines {
|
||||
namespace Internal {
|
||||
|
||||
void RegisterBuiltinForwardSceneFeatures(SceneRenderFeatureHost& featureHost) {
|
||||
featureHost.AddFeaturePass(std::make_unique<Features::BuiltinGaussianSplatPass>());
|
||||
featureHost.AddFeaturePass(std::make_unique<Features::BuiltinVolumetricPass>());
|
||||
namespace {
|
||||
|
||||
void ConfigureBuiltinForwardStandalonePasses(
|
||||
BuiltinForwardPipeline& pipeline) {
|
||||
pipeline.SetCameraFrameStandalonePass(
|
||||
CameraFrameStage::DepthOnly,
|
||||
std::make_unique<Passes::BuiltinDepthOnlyPass>());
|
||||
pipeline.SetCameraFrameStandalonePass(
|
||||
CameraFrameStage::ShadowCaster,
|
||||
std::make_unique<Passes::BuiltinShadowCasterPass>());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void ConfigureBuiltinForwardPipeline(
|
||||
BuiltinForwardPipeline& pipeline) {
|
||||
ConfigureBuiltinForwardStandalonePasses(pipeline);
|
||||
pipeline.AddForwardSceneFeaturePass(
|
||||
std::make_unique<Features::BuiltinGaussianSplatPass>());
|
||||
pipeline.AddForwardSceneFeaturePass(
|
||||
std::make_unique<Features::BuiltinVolumetricPass>());
|
||||
}
|
||||
|
||||
std::unique_ptr<BuiltinForwardPipeline>
|
||||
CreateConfiguredBuiltinForwardPipeline() {
|
||||
std::unique_ptr<BuiltinForwardPipeline> pipeline =
|
||||
std::make_unique<BuiltinForwardPipeline>();
|
||||
ConfigureBuiltinForwardPipeline(*pipeline);
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -1,14 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Rendering {
|
||||
|
||||
class SceneRenderFeatureHost;
|
||||
|
||||
namespace Pipelines {
|
||||
class BuiltinForwardPipeline;
|
||||
|
||||
namespace Internal {
|
||||
|
||||
void RegisterBuiltinForwardSceneFeatures(SceneRenderFeatureHost& featureHost);
|
||||
void ConfigureBuiltinForwardPipeline(
|
||||
BuiltinForwardPipeline& pipeline);
|
||||
std::unique_ptr<BuiltinForwardPipeline>
|
||||
CreateConfiguredBuiltinForwardPipeline();
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Pipelines
|
||||
|
||||
@@ -112,12 +112,6 @@ void ManagedScriptableRenderPipelineAsset::ConfigureCameraFramePlan(
|
||||
if (const std::shared_ptr<const ManagedRenderPipelineAssetRuntime> runtime =
|
||||
ResolveManagedAssetRuntime();
|
||||
runtime != nullptr) {
|
||||
if (runtime->UsesNativeCameraFramePlanBaseline(
|
||||
plan.request.rendererIndex)) {
|
||||
ApplyDefaultRenderPipelineAssetCameraFramePlanBaselinePolicy(
|
||||
plan,
|
||||
GetDefaultFinalColorSettings());
|
||||
}
|
||||
runtime->ConfigureCameraFramePlan(plan);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -374,9 +374,10 @@ bool NativeSceneRecorder::RecordInjectionPoint(
|
||||
}
|
||||
|
||||
bool NativeSceneRecorder::RecordFeaturePass(
|
||||
const Containers::String& featurePassName) {
|
||||
NativeSceneFeaturePassId featurePassId) {
|
||||
if (m_context.stage != CameraFrameStage::MainScene ||
|
||||
featurePassName.Empty()) {
|
||||
featurePassId ==
|
||||
NativeSceneFeaturePassId::Invalid) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -400,7 +401,7 @@ bool NativeSceneRecorder::RecordFeaturePass(
|
||||
m_clearAttachments,
|
||||
beginRecordedPass,
|
||||
endRecordedPass),
|
||||
featurePassName,
|
||||
featurePassId,
|
||||
&recordedPass)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -3,10 +3,8 @@
|
||||
#include "Rendering/Execution/DirectionalShadowExecutionState.h"
|
||||
#include "Rendering/Internal/RenderPipelineFactory.h"
|
||||
#include "Rendering/Pipelines/BuiltinForwardPipeline.h"
|
||||
#include "Rendering/Pipelines/Internal/BuiltinForwardSceneSetup.h"
|
||||
#include "Rendering/Pipelines/ManagedScriptableRenderPipelineAsset.h"
|
||||
#include "Rendering/Passes/BuiltinDepthOnlyPass.h"
|
||||
#include "Rendering/Passes/BuiltinObjectIdPass.h"
|
||||
#include "Rendering/Passes/BuiltinShadowCasterPass.h"
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Rendering {
|
||||
@@ -30,7 +28,7 @@ std::unique_ptr<RenderPipelineBackend> CreatePipelineBackendFromAsset(
|
||||
}
|
||||
}
|
||||
|
||||
return std::make_unique<BuiltinForwardPipeline>();
|
||||
return Internal::CreateConfiguredBuiltinForwardPipeline();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -214,7 +212,15 @@ RenderPass* ScriptableRenderPipelineHost::GetCameraFrameStandalonePass(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return RenderPipeline::GetCameraFrameStandalonePass(stage);
|
||||
if (RenderPass* const hostPass =
|
||||
RenderPipeline::GetCameraFrameStandalonePass(stage);
|
||||
hostPass != nullptr) {
|
||||
return hostPass;
|
||||
}
|
||||
|
||||
return ResolvePipelineBackendStandalonePass(
|
||||
stage,
|
||||
rendererIndex);
|
||||
}
|
||||
|
||||
bool ScriptableRenderPipelineHost::EnsureInitialized(const RenderContext& context) {
|
||||
@@ -260,6 +266,21 @@ bool ScriptableRenderPipelineHost::EnsureInitialized(const RenderContext& contex
|
||||
return true;
|
||||
}
|
||||
|
||||
RenderPass* ScriptableRenderPipelineHost::ResolvePipelineBackendStandalonePass(
|
||||
CameraFrameStage stage,
|
||||
int32_t rendererIndex) const {
|
||||
const auto* const backendPipeline =
|
||||
dynamic_cast<const RenderPipeline*>(m_pipelineBackend.get());
|
||||
if (backendPipeline == nullptr ||
|
||||
backendPipeline == this) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return backendPipeline->GetCameraFrameStandalonePass(
|
||||
stage,
|
||||
rendererIndex);
|
||||
}
|
||||
|
||||
void ScriptableRenderPipelineHost::BindStageRecorderPipelineBackend() {
|
||||
if (m_stageRecorder != nullptr) {
|
||||
m_stageRecorder->SetPipelineBackend(m_pipelineBackend.get());
|
||||
@@ -352,28 +373,9 @@ ScriptableRenderPipelineHostAsset::ScriptableRenderPipelineHostAsset(
|
||||
}
|
||||
|
||||
std::unique_ptr<RenderPipeline> ScriptableRenderPipelineHostAsset::CreatePipeline() const {
|
||||
std::unique_ptr<RenderPipeline> pipeline =
|
||||
std::make_unique<ScriptableRenderPipelineHost>(
|
||||
m_pipelineBackendAsset,
|
||||
m_managedAssetRuntime);
|
||||
if (pipeline != nullptr) {
|
||||
ConfigurePipeline(*pipeline);
|
||||
}
|
||||
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
void ScriptableRenderPipelineHostAsset::ConfigurePipeline(
|
||||
RenderPipeline& pipeline) const {
|
||||
pipeline.SetCameraFrameStandalonePass(
|
||||
CameraFrameStage::ObjectId,
|
||||
std::make_unique<Passes::BuiltinObjectIdPass>());
|
||||
pipeline.SetCameraFrameStandalonePass(
|
||||
CameraFrameStage::DepthOnly,
|
||||
std::make_unique<Passes::BuiltinDepthOnlyPass>());
|
||||
pipeline.SetCameraFrameStandalonePass(
|
||||
CameraFrameStage::ShadowCaster,
|
||||
std::make_unique<Passes::BuiltinShadowCasterPass>());
|
||||
return std::make_unique<ScriptableRenderPipelineHost>(
|
||||
m_pipelineBackendAsset,
|
||||
m_managedAssetRuntime);
|
||||
}
|
||||
|
||||
FinalColorSettings ScriptableRenderPipelineHostAsset::GetDefaultFinalColorSettings() const {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "Rendering/Execution/Internal/CameraFrameGraph/SurfaceUtils.h"
|
||||
#include "Rendering/FrameData/RenderSceneData.h"
|
||||
#include "Rendering/Graph/RenderGraph.h"
|
||||
#include "RHI/RHIResourceView.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
@@ -146,13 +147,65 @@ bool ResolveGraphManagedOutputSurface(
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ResolveGraphManagedTextureBindingViews(
|
||||
const std::vector<RenderPassGraphTextureBindingRequest>&
|
||||
textureBindingRequests,
|
||||
RenderGraphTextureHandle sourceColorTexture,
|
||||
RHI::RHIResourceView* sourceColorView,
|
||||
const RenderGraphExecutionContext& graphContext,
|
||||
std::vector<RenderPassContext::TextureBindingView>&
|
||||
outTextureBindings) {
|
||||
outTextureBindings.clear();
|
||||
outTextureBindings.reserve(textureBindingRequests.size());
|
||||
|
||||
for (const RenderPassGraphTextureBindingRequest& bindingRequest :
|
||||
textureBindingRequests) {
|
||||
if (bindingRequest.resourceName.Empty() ||
|
||||
!bindingRequest.texture.IsValid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RHI::RHIResourceView* resolvedView = nullptr;
|
||||
if (sourceColorTexture.IsValid() &&
|
||||
bindingRequest.texture.index ==
|
||||
sourceColorTexture.index) {
|
||||
resolvedView = sourceColorView;
|
||||
} else {
|
||||
resolvedView =
|
||||
graphContext.ResolveTextureView(
|
||||
bindingRequest.texture,
|
||||
RenderGraphTextureViewType::
|
||||
ShaderResource);
|
||||
}
|
||||
|
||||
if (resolvedView == nullptr ||
|
||||
resolvedView->GetViewType() !=
|
||||
RHI::ResourceViewType::ShaderResource) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RenderPassContext::TextureBindingView
|
||||
resolvedBinding = {};
|
||||
resolvedBinding.resourceName =
|
||||
bindingRequest.resourceName;
|
||||
resolvedBinding.resourceView = resolvedView;
|
||||
outTextureBindings.push_back(
|
||||
std::move(resolvedBinding));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool RecordCallbackRasterRenderPass(
|
||||
const RenderPassRenderGraphContext& context,
|
||||
const RenderPassGraphIO& io,
|
||||
RenderPassGraphExecutePassCallback executePassCallback,
|
||||
std::vector<RenderGraphTextureHandle> additionalReadTextures) {
|
||||
std::vector<RenderGraphTextureHandle> additionalReadTextures,
|
||||
std::vector<RenderGraphTextureHandle> additionalReadDepthTextures,
|
||||
std::vector<RenderPassGraphTextureBindingRequest>
|
||||
textureBindingRequests) {
|
||||
if (!executePassCallback) {
|
||||
return false;
|
||||
}
|
||||
@@ -191,6 +244,8 @@ bool RecordCallbackRasterRenderPass(
|
||||
endPassCallback,
|
||||
executePassCallback,
|
||||
additionalReadTextures,
|
||||
additionalReadDepthTextures,
|
||||
textureBindingRequests,
|
||||
io](
|
||||
RenderGraphPassBuilder& passBuilder) {
|
||||
if (io.readSourceColor && sourceColorTexture.IsValid()) {
|
||||
@@ -203,6 +258,13 @@ bool RecordCallbackRasterRenderPass(
|
||||
}
|
||||
}
|
||||
|
||||
for (RenderGraphTextureHandle readDepthTexture :
|
||||
additionalReadDepthTextures) {
|
||||
if (readDepthTexture.IsValid()) {
|
||||
passBuilder.ReadDepthTexture(readDepthTexture);
|
||||
}
|
||||
}
|
||||
|
||||
if (io.writeColor) {
|
||||
for (RenderGraphTextureHandle colorTarget : colorTargets) {
|
||||
if (colorTarget.IsValid()) {
|
||||
@@ -230,6 +292,7 @@ bool RecordCallbackRasterRenderPass(
|
||||
beginPassCallback,
|
||||
endPassCallback,
|
||||
executePassCallback,
|
||||
textureBindingRequests,
|
||||
io](
|
||||
const RenderGraphExecutionContext& executionContext) {
|
||||
if (executionSucceeded != nullptr && !(*executionSucceeded)) {
|
||||
@@ -274,13 +337,28 @@ bool RecordCallbackRasterRenderPass(
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<RenderPassContext::TextureBindingView>
|
||||
resolvedTextureBindings = {};
|
||||
if (!ResolveGraphManagedTextureBindingViews(
|
||||
textureBindingRequests,
|
||||
sourceColorTexture,
|
||||
resolvedSourceColorView,
|
||||
executionContext,
|
||||
resolvedTextureBindings)) {
|
||||
if (executionSucceeded != nullptr) {
|
||||
*executionSucceeded = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const RenderPassContext passContext = {
|
||||
renderContext,
|
||||
*resolvedSurface,
|
||||
*sceneData,
|
||||
resolvedSourceSurface,
|
||||
resolvedSourceColorView,
|
||||
resolvedSourceColorState
|
||||
resolvedSourceColorState,
|
||||
std::move(resolvedTextureBindings)
|
||||
};
|
||||
if (beginPassCallback &&
|
||||
!beginPassCallback(passContext)) {
|
||||
|
||||
@@ -48,12 +48,13 @@ Containers::String BuildNamedFeatureGraphPassName(
|
||||
return Containers::String(name.c_str());
|
||||
}
|
||||
|
||||
bool MatchesFeaturePassName(
|
||||
bool MatchesFeaturePassId(
|
||||
const SceneRenderFeaturePass& featurePass,
|
||||
const Containers::String& featurePassName) {
|
||||
const char* const passName = featurePass.GetName();
|
||||
return passName != nullptr &&
|
||||
featurePassName == Containers::String(passName);
|
||||
NativeSceneFeaturePassId featurePassId) {
|
||||
return featurePassId !=
|
||||
NativeSceneFeaturePassId::Invalid &&
|
||||
featurePass.GetNativeSceneFeaturePassId() ==
|
||||
featurePassId;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -180,13 +181,14 @@ bool SceneRenderFeatureHost::Record(
|
||||
|
||||
bool SceneRenderFeatureHost::RecordFeaturePass(
|
||||
const SceneRenderFeaturePassRenderGraphContext& context,
|
||||
const Containers::String& featurePassName,
|
||||
NativeSceneFeaturePassId featurePassId,
|
||||
bool* recordedPass) const {
|
||||
if (recordedPass != nullptr) {
|
||||
*recordedPass = false;
|
||||
}
|
||||
|
||||
if (featurePassName.Empty()) {
|
||||
if (featurePassId ==
|
||||
NativeSceneFeaturePassId::Invalid) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -196,7 +198,9 @@ bool SceneRenderFeatureHost::RecordFeaturePass(
|
||||
m_featurePasses[featureIndex];
|
||||
SceneRenderFeaturePass* const featurePass = featurePassOwner.get();
|
||||
if (featurePass == nullptr ||
|
||||
!MatchesFeaturePassName(*featurePass, featurePassName)) {
|
||||
!MatchesFeaturePassId(
|
||||
*featurePass,
|
||||
featurePassId)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -217,7 +221,7 @@ bool SceneRenderFeatureHost::RecordFeaturePass(
|
||||
Debug::LogCategory::Rendering,
|
||||
(Containers::String(
|
||||
"SceneRenderFeatureHost record failed for feature pass '") +
|
||||
featurePassName +
|
||||
featurePass->GetName() +
|
||||
"': " +
|
||||
featurePass->GetName())
|
||||
.CStr());
|
||||
@@ -233,8 +237,12 @@ bool SceneRenderFeatureHost::RecordFeaturePass(
|
||||
Debug::Logger::Get().Error(
|
||||
Debug::LogCategory::Rendering,
|
||||
(Containers::String(
|
||||
"SceneRenderFeatureHost could not resolve feature pass: ") +
|
||||
featurePassName)
|
||||
"SceneRenderFeatureHost could not resolve feature pass id: ") +
|
||||
Containers::String(
|
||||
std::to_string(
|
||||
static_cast<uint32_t>(
|
||||
featurePassId))
|
||||
.c_str()))
|
||||
.CStr());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -118,7 +118,11 @@ struct ManagedScriptableRenderContextState {
|
||||
Rendering::FullscreenPassDesc passDesc = {};
|
||||
Rendering::RenderGraphTextureHandle sourceColorTexture = {};
|
||||
std::vector<Rendering::RenderGraphTextureHandle> readTextures = {};
|
||||
std::vector<Rendering::RenderGraphTextureHandle> readDepthTextures = {};
|
||||
std::vector<Rendering::RenderPassGraphTextureBindingRequest>
|
||||
textureBindings = {};
|
||||
std::vector<Rendering::RenderGraphTextureHandle> colorTargets = {};
|
||||
Rendering::RenderGraphTextureHandle depthTarget = {};
|
||||
};
|
||||
uint64_t nextPendingRasterPassHandle = 1u;
|
||||
std::unordered_map<uint64_t, RasterPassRecordRequest>
|
||||
@@ -420,6 +424,10 @@ bool RecordManagedFullscreenRasterPass(
|
||||
Rendering::RenderGraphTextureHandle sourceColorTexture,
|
||||
std::vector<Rendering::RenderGraphTextureHandle> colorTargets,
|
||||
std::vector<Rendering::RenderGraphTextureHandle> additionalReadTextures,
|
||||
std::vector<Rendering::RenderGraphTextureHandle> additionalReadDepthTextures,
|
||||
std::vector<Rendering::RenderPassGraphTextureBindingRequest>
|
||||
textureBindings,
|
||||
Rendering::RenderGraphTextureHandle depthTarget,
|
||||
const Containers::String& passName) {
|
||||
if (!Rendering::IsCameraFrameFullscreenSequenceStage(stageContext.stage) ||
|
||||
!sourceColorTexture.IsValid() ||
|
||||
@@ -442,7 +450,7 @@ bool RecordManagedFullscreenRasterPass(
|
||||
params.overrideColorTargets = true;
|
||||
params.colorTargets = std::move(colorTargets);
|
||||
params.overrideDepthTarget = true;
|
||||
params.depthTarget = {};
|
||||
params.depthTarget = depthTarget;
|
||||
|
||||
const Rendering::RenderGraphRecordingContext recordingContext =
|
||||
Rendering::BuildRenderGraphRecordingContext(
|
||||
@@ -451,14 +459,19 @@ bool RecordManagedFullscreenRasterPass(
|
||||
const Rendering::RenderPassRenderGraphContext renderGraphContext =
|
||||
Rendering::BuildRenderPassRenderGraphContext(recordingContext);
|
||||
Rendering::RenderPass* const passPtr = &pass;
|
||||
Rendering::RenderPassGraphIO io =
|
||||
Rendering::BuildSourceColorFullscreenRasterPassGraphIO();
|
||||
io.writeDepth = depthTarget.IsValid();
|
||||
return Rendering::RecordCallbackRasterRenderPass(
|
||||
renderGraphContext,
|
||||
Rendering::BuildSourceColorFullscreenRasterPassGraphIO(),
|
||||
io,
|
||||
[passPtr](const Rendering::RenderPassContext& passContext) {
|
||||
return passPtr != nullptr &&
|
||||
passPtr->Execute(passContext);
|
||||
},
|
||||
std::move(additionalReadTextures));
|
||||
std::move(additionalReadTextures),
|
||||
std::move(additionalReadDepthTextures),
|
||||
std::move(textureBindings));
|
||||
}
|
||||
|
||||
bool RecordManagedFullscreenPassToTexture(
|
||||
@@ -473,6 +486,9 @@ bool RecordManagedFullscreenPassToTexture(
|
||||
sourceColorTexture,
|
||||
{ outputColorTexture },
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
passName);
|
||||
}
|
||||
|
||||
@@ -1042,6 +1058,26 @@ static_assert(
|
||||
sizeof(Rendering::FinalColorSettings),
|
||||
"Managed final color bridge layout must match native FinalColorSettings.");
|
||||
|
||||
struct ManagedFinalColorOverrideSettingsData {
|
||||
uint8_t overrideOutputTransferMode = 0u;
|
||||
uint8_t outputTransferMode = 0u;
|
||||
uint8_t overrideExposureMode = 0u;
|
||||
uint8_t exposureMode = 0u;
|
||||
uint8_t overrideExposureValue = 0u;
|
||||
uint8_t exposureValuePadding[3] = {};
|
||||
float exposureValue = 1.0f;
|
||||
uint8_t overrideToneMappingMode = 0u;
|
||||
uint8_t toneMappingMode = 0u;
|
||||
uint8_t overrideFinalColorScale = 0u;
|
||||
uint8_t finalColorScalePadding = 0u;
|
||||
XCEngine::Math::Vector4 finalColorScale = XCEngine::Math::Vector4::One();
|
||||
};
|
||||
|
||||
static_assert(
|
||||
sizeof(ManagedFinalColorOverrideSettingsData) ==
|
||||
sizeof(Rendering::FinalColorOverrideSettings),
|
||||
"Managed final color override bridge layout must match native FinalColorOverrideSettings.");
|
||||
|
||||
struct ManagedRenderGraphTextureDescData {
|
||||
uint32_t width = 0u;
|
||||
uint32_t height = 0u;
|
||||
@@ -1377,6 +1413,42 @@ Rendering::FinalColorSettings BuildManagedFinalColorSettings(
|
||||
return settings;
|
||||
}
|
||||
|
||||
ManagedFinalColorOverrideSettingsData BuildManagedFinalColorOverrideSettings(
|
||||
const Rendering::FinalColorOverrideSettings& nativeSettings) {
|
||||
ManagedFinalColorOverrideSettingsData managedSettings = {};
|
||||
managedSettings.overrideOutputTransferMode =
|
||||
nativeSettings.overrideOutputTransferMode
|
||||
? 1u
|
||||
: 0u;
|
||||
managedSettings.outputTransferMode =
|
||||
static_cast<uint8_t>(nativeSettings.outputTransferMode);
|
||||
managedSettings.overrideExposureMode =
|
||||
nativeSettings.overrideExposureMode
|
||||
? 1u
|
||||
: 0u;
|
||||
managedSettings.exposureMode =
|
||||
static_cast<uint8_t>(nativeSettings.exposureMode);
|
||||
managedSettings.overrideExposureValue =
|
||||
nativeSettings.overrideExposureValue
|
||||
? 1u
|
||||
: 0u;
|
||||
managedSettings.exposureValue =
|
||||
nativeSettings.exposureValue;
|
||||
managedSettings.overrideToneMappingMode =
|
||||
nativeSettings.overrideToneMappingMode
|
||||
? 1u
|
||||
: 0u;
|
||||
managedSettings.toneMappingMode =
|
||||
static_cast<uint8_t>(nativeSettings.toneMappingMode);
|
||||
managedSettings.overrideFinalColorScale =
|
||||
nativeSettings.overrideFinalColorScale
|
||||
? 1u
|
||||
: 0u;
|
||||
managedSettings.finalColorScale =
|
||||
nativeSettings.finalColorScale;
|
||||
return managedSettings;
|
||||
}
|
||||
|
||||
bool SupportsManagedRenderPipelineStageGraphRecording(
|
||||
Rendering::CameraFrameStage stage) {
|
||||
return Rendering::SupportsCameraFramePipelineGraphRecording(stage) ||
|
||||
@@ -1499,9 +1571,6 @@ public:
|
||||
Rendering::FinalColorSettings& settings) const override;
|
||||
std::shared_ptr<const Rendering::RenderPipelineAsset>
|
||||
GetSharedPipelineBackendAsset() const override;
|
||||
bool UsesNativeCameraFramePlanBaseline() const override;
|
||||
bool UsesNativeCameraFramePlanBaseline(
|
||||
int32_t rendererIndex) const override;
|
||||
|
||||
MonoScriptRuntime* GetRuntime() const {
|
||||
return m_runtime;
|
||||
@@ -1532,10 +1601,6 @@ private:
|
||||
MonoObject* assetObject) const;
|
||||
MonoMethod* ResolveGetRuntimeResourceVersionMethod(
|
||||
MonoObject* assetObject) const;
|
||||
MonoMethod* ResolveUsesNativeCameraFramePlanBaselineMethod(
|
||||
MonoObject* assetObject) const;
|
||||
MonoMethod* ResolveUsesNativeCameraFramePlanBaselineContextualMethod(
|
||||
MonoObject* assetObject) const;
|
||||
MonoMethod* ResolveConfigureRenderSceneSetupMethod(
|
||||
MonoObject* assetObject) const;
|
||||
MonoMethod* ResolveConfigureDirectionalShadowExecutionStateMethod(
|
||||
@@ -1553,11 +1618,6 @@ private:
|
||||
mutable MonoMethod* m_configureCameraFramePlanMethod = nullptr;
|
||||
mutable MonoMethod* m_getDefaultFinalColorSettingsMethod = nullptr;
|
||||
mutable MonoMethod* m_getRuntimeResourceVersionMethod = nullptr;
|
||||
mutable MonoMethod* m_usesNativeCameraFramePlanBaselineMethod =
|
||||
nullptr;
|
||||
mutable MonoMethod*
|
||||
m_usesNativeCameraFramePlanBaselineContextualMethod =
|
||||
nullptr;
|
||||
mutable MonoMethod* m_configureRenderSceneSetupMethod =
|
||||
nullptr;
|
||||
mutable MonoMethod*
|
||||
@@ -1890,6 +1950,9 @@ private:
|
||||
resolvedSourceColor,
|
||||
resolvedColorTargets,
|
||||
request.readTextures,
|
||||
request.readDepthTextures,
|
||||
request.textureBindings,
|
||||
request.depthTarget,
|
||||
resolvedPassName)) {
|
||||
return false;
|
||||
}
|
||||
@@ -2203,66 +2266,6 @@ MonoManagedRenderPipelineAssetRuntime::GetSharedPipelineBackendAsset() const {
|
||||
return m_sharedPipelineBackendAsset;
|
||||
}
|
||||
|
||||
bool MonoManagedRenderPipelineAssetRuntime::UsesNativeCameraFramePlanBaseline()
|
||||
const {
|
||||
return UsesNativeCameraFramePlanBaseline(-1);
|
||||
}
|
||||
|
||||
bool MonoManagedRenderPipelineAssetRuntime::UsesNativeCameraFramePlanBaseline(
|
||||
int32_t rendererIndex) const {
|
||||
if (!SyncManagedAssetRuntimeState()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MonoObject* const assetObject = GetManagedAssetObject();
|
||||
if (assetObject == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MonoMethod* const contextualMethod =
|
||||
ResolveUsesNativeCameraFramePlanBaselineContextualMethod(
|
||||
assetObject);
|
||||
if (contextualMethod != nullptr) {
|
||||
void* args[1] = { &rendererIndex };
|
||||
MonoObject* managedValueObject = nullptr;
|
||||
if (!m_runtime->InvokeManagedMethod(
|
||||
assetObject,
|
||||
contextualMethod,
|
||||
args,
|
||||
&managedValueObject)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool usesBaseline = false;
|
||||
return TryUnboxManagedBoolean(
|
||||
managedValueObject,
|
||||
usesBaseline) &&
|
||||
usesBaseline;
|
||||
}
|
||||
|
||||
MonoMethod* const method =
|
||||
ResolveUsesNativeCameraFramePlanBaselineMethod(
|
||||
assetObject);
|
||||
if (method == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MonoObject* managedValueObject = nullptr;
|
||||
if (!m_runtime->InvokeManagedMethod(
|
||||
assetObject,
|
||||
method,
|
||||
nullptr,
|
||||
&managedValueObject)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool usesBaseline = false;
|
||||
return TryUnboxManagedBoolean(
|
||||
managedValueObject,
|
||||
usesBaseline) &&
|
||||
usesBaseline;
|
||||
}
|
||||
|
||||
bool MonoManagedRenderPipelineAssetRuntime::AcquireManagedPipelineHandle(
|
||||
uint32_t& outPipelineHandle) const {
|
||||
if (!SyncManagedAssetRuntimeState()) {
|
||||
@@ -2467,8 +2470,6 @@ void MonoManagedRenderPipelineAssetRuntime::ReleaseManagedAsset() const {
|
||||
m_configureCameraFramePlanMethod = nullptr;
|
||||
m_getDefaultFinalColorSettingsMethod = nullptr;
|
||||
m_getRuntimeResourceVersionMethod = nullptr;
|
||||
m_usesNativeCameraFramePlanBaselineMethod = nullptr;
|
||||
m_usesNativeCameraFramePlanBaselineContextualMethod = nullptr;
|
||||
m_configureRenderSceneSetupMethod = nullptr;
|
||||
m_configureDirectionalShadowExecutionStateMethod = nullptr;
|
||||
m_sharedPipelineBackendAsset.reset();
|
||||
@@ -2590,37 +2591,6 @@ MonoManagedRenderPipelineAssetRuntime::ResolveGetRuntimeResourceVersionMethod(
|
||||
return m_getRuntimeResourceVersionMethod;
|
||||
}
|
||||
|
||||
MonoMethod*
|
||||
MonoManagedRenderPipelineAssetRuntime::
|
||||
ResolveUsesNativeCameraFramePlanBaselineMethod(
|
||||
MonoObject* assetObject) const {
|
||||
if (m_usesNativeCameraFramePlanBaselineMethod == nullptr) {
|
||||
m_usesNativeCameraFramePlanBaselineMethod =
|
||||
m_runtime->ResolveManagedMethod(
|
||||
assetObject,
|
||||
"UsesNativeCameraFramePlanBaseline",
|
||||
0);
|
||||
}
|
||||
|
||||
return m_usesNativeCameraFramePlanBaselineMethod;
|
||||
}
|
||||
|
||||
MonoMethod*
|
||||
MonoManagedRenderPipelineAssetRuntime::
|
||||
ResolveUsesNativeCameraFramePlanBaselineContextualMethod(
|
||||
MonoObject* assetObject) const {
|
||||
if (m_usesNativeCameraFramePlanBaselineContextualMethod ==
|
||||
nullptr) {
|
||||
m_usesNativeCameraFramePlanBaselineContextualMethod =
|
||||
m_runtime->ResolveManagedMethod(
|
||||
assetObject,
|
||||
"UsesNativeCameraFramePlanBaselineContextual",
|
||||
1);
|
||||
}
|
||||
|
||||
return m_usesNativeCameraFramePlanBaselineContextualMethod;
|
||||
}
|
||||
|
||||
MonoMethod*
|
||||
MonoManagedRenderPipelineAssetRuntime::
|
||||
ResolveConfigureRenderSceneSetupMethod(
|
||||
@@ -4010,6 +3980,124 @@ void InternalCall_Camera_SetPrimary(uint64_t gameObjectUUID, mono_bool value) {
|
||||
component->SetPrimary(value != 0);
|
||||
}
|
||||
|
||||
int32_t InternalCall_Camera_GetClearMode(uint64_t gameObjectUUID) {
|
||||
Components::CameraComponent* component = FindCameraComponent(gameObjectUUID);
|
||||
return component != nullptr
|
||||
? static_cast<int32_t>(component->GetClearMode())
|
||||
: 0;
|
||||
}
|
||||
|
||||
void InternalCall_Camera_SetClearMode(uint64_t gameObjectUUID, int32_t value) {
|
||||
Components::CameraComponent* component = FindCameraComponent(gameObjectUUID);
|
||||
if (!component) {
|
||||
return;
|
||||
}
|
||||
|
||||
component->SetClearMode(
|
||||
static_cast<Components::CameraClearMode>(value));
|
||||
}
|
||||
|
||||
int32_t InternalCall_Camera_GetStackType(uint64_t gameObjectUUID) {
|
||||
Components::CameraComponent* component = FindCameraComponent(gameObjectUUID);
|
||||
return component != nullptr
|
||||
? static_cast<int32_t>(component->GetStackType())
|
||||
: 0;
|
||||
}
|
||||
|
||||
void InternalCall_Camera_SetStackType(uint64_t gameObjectUUID, int32_t value) {
|
||||
Components::CameraComponent* component = FindCameraComponent(gameObjectUUID);
|
||||
if (!component) {
|
||||
return;
|
||||
}
|
||||
|
||||
component->SetStackType(
|
||||
static_cast<Components::CameraStackType>(value));
|
||||
}
|
||||
|
||||
int32_t InternalCall_Camera_GetProjectionType(uint64_t gameObjectUUID) {
|
||||
Components::CameraComponent* component = FindCameraComponent(gameObjectUUID);
|
||||
return component != nullptr
|
||||
? static_cast<int32_t>(component->GetProjectionType())
|
||||
: 0;
|
||||
}
|
||||
|
||||
mono_bool InternalCall_Camera_GetSkyboxEnabled(uint64_t gameObjectUUID) {
|
||||
Components::CameraComponent* component = FindCameraComponent(gameObjectUUID);
|
||||
return (component && component->IsSkyboxEnabled()) ? 1 : 0;
|
||||
}
|
||||
|
||||
mono_bool InternalCall_Camera_GetHasSkyboxMaterial(uint64_t gameObjectUUID) {
|
||||
Components::CameraComponent* component = FindCameraComponent(gameObjectUUID);
|
||||
return (component && component->GetSkyboxMaterial() != nullptr) ? 1 : 0;
|
||||
}
|
||||
|
||||
mono_bool InternalCall_Camera_GetHasFinalColorOverrides(
|
||||
uint64_t gameObjectUUID) {
|
||||
Components::CameraComponent* component =
|
||||
FindCameraComponent(gameObjectUUID);
|
||||
return (component &&
|
||||
component->GetFinalColorOverrides().HasOverrides())
|
||||
? 1
|
||||
: 0;
|
||||
}
|
||||
|
||||
void InternalCall_Camera_GetFinalColorOverrideSettings(
|
||||
uint64_t gameObjectUUID,
|
||||
ManagedFinalColorOverrideSettingsData* outSettings) {
|
||||
if (outSettings == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
Components::CameraComponent* component =
|
||||
FindCameraComponent(gameObjectUUID);
|
||||
const Rendering::FinalColorOverrideSettings sourceSettings =
|
||||
component != nullptr
|
||||
? component->GetFinalColorOverrides()
|
||||
: Rendering::FinalColorOverrideSettings{};
|
||||
*outSettings =
|
||||
BuildManagedFinalColorOverrideSettings(
|
||||
sourceSettings);
|
||||
}
|
||||
|
||||
void InternalCall_Camera_GetSkyboxTopColor(
|
||||
uint64_t gameObjectUUID,
|
||||
XCEngine::Math::Color* outColor) {
|
||||
if (outColor == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
Components::CameraComponent* component = FindCameraComponent(gameObjectUUID);
|
||||
*outColor = component != nullptr
|
||||
? component->GetSkyboxTopColor()
|
||||
: XCEngine::Math::Color();
|
||||
}
|
||||
|
||||
void InternalCall_Camera_GetSkyboxHorizonColor(
|
||||
uint64_t gameObjectUUID,
|
||||
XCEngine::Math::Color* outColor) {
|
||||
if (outColor == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
Components::CameraComponent* component = FindCameraComponent(gameObjectUUID);
|
||||
*outColor = component != nullptr
|
||||
? component->GetSkyboxHorizonColor()
|
||||
: XCEngine::Math::Color();
|
||||
}
|
||||
|
||||
void InternalCall_Camera_GetSkyboxBottomColor(
|
||||
uint64_t gameObjectUUID,
|
||||
XCEngine::Math::Color* outColor) {
|
||||
if (outColor == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
Components::CameraComponent* component = FindCameraComponent(gameObjectUUID);
|
||||
*outColor = component != nullptr
|
||||
? component->GetSkyboxBottomColor()
|
||||
: XCEngine::Math::Color();
|
||||
}
|
||||
|
||||
float InternalCall_Light_GetIntensity(uint64_t gameObjectUUID) {
|
||||
Components::LightComponent* component = FindLightComponent(gameObjectUUID);
|
||||
return component ? component->GetIntensity() : 0.0f;
|
||||
@@ -4622,6 +4710,94 @@ InternalCall_Rendering_ScriptableRenderContext_AddRasterPassReadTexture(
|
||||
return 1;
|
||||
}
|
||||
|
||||
mono_bool
|
||||
InternalCall_Rendering_ScriptableRenderContext_AddRasterPassReadDepthTexture(
|
||||
uint64_t nativeHandle,
|
||||
uint64_t rasterPassHandle,
|
||||
int32_t textureHandle) {
|
||||
ManagedScriptableRenderContextState* const state =
|
||||
FindManagedScriptableRenderContextState(nativeHandle);
|
||||
ManagedScriptableRenderContextState::RasterPassRecordRequest*
|
||||
const request =
|
||||
FindPendingManagedRasterPassRecordRequest(
|
||||
state,
|
||||
rasterPassHandle);
|
||||
if (request == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const Rendering::RenderGraphTextureHandle readDepthTexture =
|
||||
DecodeManagedRenderGraphTextureHandle(
|
||||
textureHandle);
|
||||
if (!readDepthTexture.IsValid()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
request->readDepthTextures.push_back(readDepthTexture);
|
||||
return 1;
|
||||
}
|
||||
|
||||
mono_bool
|
||||
InternalCall_Rendering_ScriptableRenderContext_AddRasterPassTextureBinding(
|
||||
uint64_t nativeHandle,
|
||||
uint64_t rasterPassHandle,
|
||||
MonoString* shaderResourceName,
|
||||
int32_t textureHandle,
|
||||
mono_bool isDepth) {
|
||||
ManagedScriptableRenderContextState* const state =
|
||||
FindManagedScriptableRenderContextState(nativeHandle);
|
||||
ManagedScriptableRenderContextState::RasterPassRecordRequest*
|
||||
const request =
|
||||
FindPendingManagedRasterPassRecordRequest(
|
||||
state,
|
||||
rasterPassHandle);
|
||||
if (request == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const Containers::String shaderResourceNameString(
|
||||
MonoStringToUtf8(shaderResourceName).c_str());
|
||||
if (shaderResourceNameString.Empty()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const Rendering::RenderGraphTextureHandle texture =
|
||||
DecodeManagedRenderGraphTextureHandle(
|
||||
textureHandle);
|
||||
if (!texture.IsValid()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Rendering::RenderPassGraphTextureBindingRequest
|
||||
bindingRequest = {};
|
||||
bindingRequest.resourceName =
|
||||
shaderResourceNameString;
|
||||
bindingRequest.texture = texture;
|
||||
bindingRequest.aspect =
|
||||
isDepth != 0
|
||||
? Rendering::RenderGraphTextureAspect::Depth
|
||||
: Rendering::RenderGraphTextureAspect::Color;
|
||||
|
||||
auto existingBinding =
|
||||
std::find_if(
|
||||
request->textureBindings.begin(),
|
||||
request->textureBindings.end(),
|
||||
[&shaderResourceNameString](
|
||||
const Rendering::RenderPassGraphTextureBindingRequest&
|
||||
existingRequest) {
|
||||
return existingRequest.resourceName ==
|
||||
shaderResourceNameString;
|
||||
});
|
||||
if (existingBinding != request->textureBindings.end()) {
|
||||
*existingBinding = std::move(bindingRequest);
|
||||
} else {
|
||||
request->textureBindings.push_back(
|
||||
std::move(bindingRequest));
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
mono_bool
|
||||
InternalCall_Rendering_ScriptableRenderContext_SetRasterPassColorAttachment(
|
||||
uint64_t nativeHandle,
|
||||
@@ -4658,6 +4834,33 @@ InternalCall_Rendering_ScriptableRenderContext_SetRasterPassColorAttachment(
|
||||
return 1;
|
||||
}
|
||||
|
||||
mono_bool
|
||||
InternalCall_Rendering_ScriptableRenderContext_SetRasterPassDepthAttachment(
|
||||
uint64_t nativeHandle,
|
||||
uint64_t rasterPassHandle,
|
||||
int32_t textureHandle) {
|
||||
ManagedScriptableRenderContextState* const state =
|
||||
FindManagedScriptableRenderContextState(nativeHandle);
|
||||
ManagedScriptableRenderContextState::RasterPassRecordRequest*
|
||||
const request =
|
||||
FindPendingManagedRasterPassRecordRequest(
|
||||
state,
|
||||
rasterPassHandle);
|
||||
if (request == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const Rendering::RenderGraphTextureHandle depthAttachment =
|
||||
DecodeManagedRenderGraphTextureHandle(
|
||||
textureHandle);
|
||||
if (!depthAttachment.IsValid()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
request->depthTarget = depthAttachment;
|
||||
return 1;
|
||||
}
|
||||
|
||||
mono_bool
|
||||
InternalCall_Rendering_ScriptableRenderContext_SetRasterPassColorScaleFullscreenExecution(
|
||||
uint64_t nativeHandle,
|
||||
@@ -5321,7 +5524,7 @@ InternalCall_Rendering_ScriptableRenderContext_RecordSceneInjectionPoint(
|
||||
mono_bool
|
||||
InternalCall_Rendering_ScriptableRenderContext_RecordNativeSceneFeaturePass(
|
||||
uint64_t nativeHandle,
|
||||
MonoString* featurePassName) {
|
||||
int32_t featurePassId) {
|
||||
ManagedScriptableRenderContextState* const state =
|
||||
FindManagedScriptableRenderContextState(nativeHandle);
|
||||
if (state == nullptr ||
|
||||
@@ -5331,14 +5534,17 @@ InternalCall_Rendering_ScriptableRenderContext_RecordNativeSceneFeaturePass(
|
||||
return 0;
|
||||
}
|
||||
|
||||
const std::string featurePassNameUtf8 =
|
||||
MonoStringToUtf8(featurePassName);
|
||||
if (featurePassNameUtf8.empty()) {
|
||||
const Rendering::NativeSceneFeaturePassId
|
||||
resolvedFeaturePassId =
|
||||
static_cast<Rendering::NativeSceneFeaturePassId>(
|
||||
featurePassId);
|
||||
if (resolvedFeaturePassId ==
|
||||
Rendering::NativeSceneFeaturePassId::Invalid) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return state->sceneRecorder->RecordFeaturePass(
|
||||
Containers::String(featurePassNameUtf8.c_str()))
|
||||
resolvedFeaturePassId)
|
||||
? 1
|
||||
: 0;
|
||||
}
|
||||
@@ -5519,6 +5725,74 @@ void InternalCall_Rendering_CameraRenderRequestContext_ClearDirectionalShadow(
|
||||
state->suppressDirectionalShadow = true;
|
||||
}
|
||||
|
||||
int32_t InternalCall_Rendering_CameraRenderRequestContext_GetClearFlags(
|
||||
uint64_t nativeHandle) {
|
||||
const ManagedCameraRenderRequestContextState* const state =
|
||||
FindManagedCameraRenderRequestContextState(nativeHandle);
|
||||
return state != nullptr &&
|
||||
state->request != nullptr
|
||||
? static_cast<int32_t>(state->request->clearFlags)
|
||||
: static_cast<int32_t>(Rendering::RenderClearFlags::All);
|
||||
}
|
||||
|
||||
void InternalCall_Rendering_CameraRenderRequestContext_SetClearFlags(
|
||||
uint64_t nativeHandle,
|
||||
int32_t clearFlags) {
|
||||
ManagedCameraRenderRequestContextState* const state =
|
||||
FindManagedCameraRenderRequestContextState(nativeHandle);
|
||||
if (state == nullptr || state->request == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
state->request->clearFlags =
|
||||
static_cast<Rendering::RenderClearFlags>(clearFlags);
|
||||
}
|
||||
|
||||
void InternalCall_Rendering_CameraRenderRequestContext_SetResolvedFinalColorPolicy(
|
||||
uint64_t nativeHandle,
|
||||
ManagedFinalColorSettingsData* settings,
|
||||
mono_bool hasPipelineDefaults,
|
||||
mono_bool hasCameraOverrides) {
|
||||
ManagedCameraRenderRequestContextState* const state =
|
||||
FindManagedCameraRenderRequestContextState(nativeHandle);
|
||||
if (state == nullptr ||
|
||||
state->request == nullptr ||
|
||||
settings == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
const Rendering::FinalColorSettings resolvedSettings =
|
||||
BuildManagedFinalColorSettings(*settings);
|
||||
Rendering::ResolvedFinalColorPolicy resolvedPolicy = {};
|
||||
resolvedPolicy.outputTransferMode =
|
||||
resolvedSettings.outputTransferMode;
|
||||
resolvedPolicy.exposureMode =
|
||||
resolvedSettings.exposureMode;
|
||||
resolvedPolicy.exposureValue =
|
||||
resolvedSettings.exposureValue;
|
||||
resolvedPolicy.toneMappingMode =
|
||||
resolvedSettings.toneMappingMode;
|
||||
resolvedPolicy.finalColorScale =
|
||||
resolvedSettings.finalColorScale;
|
||||
resolvedPolicy.hasPipelineDefaults =
|
||||
hasPipelineDefaults != 0;
|
||||
resolvedPolicy.hasCameraOverrides =
|
||||
hasCameraOverrides != 0;
|
||||
state->request->finalColorPolicy =
|
||||
resolvedPolicy;
|
||||
}
|
||||
|
||||
void InternalCall_Rendering_CameraRenderRequestContext_ClearFinalColorPolicy(
|
||||
uint64_t nativeHandle) {
|
||||
ManagedCameraRenderRequestContextState* const state =
|
||||
FindManagedCameraRenderRequestContextState(nativeHandle);
|
||||
if (state == nullptr || state->request == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
state->request->finalColorPolicy = {};
|
||||
}
|
||||
|
||||
int32_t
|
||||
InternalCall_Rendering_RenderSceneSetupContext_GetRendererIndex(
|
||||
uint64_t nativeHandle) {
|
||||
@@ -5530,6 +5804,21 @@ InternalCall_Rendering_RenderSceneSetupContext_GetRendererIndex(
|
||||
: -1;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
InternalCall_Rendering_RenderSceneSetupContext_GetCameraGameObjectUUID(
|
||||
uint64_t nativeHandle) {
|
||||
const ManagedRenderSceneSetupContextState* const state =
|
||||
FindManagedRenderSceneSetupContextState(nativeHandle);
|
||||
if (state == nullptr ||
|
||||
state->plan == nullptr ||
|
||||
state->plan->request.camera == nullptr ||
|
||||
state->plan->request.camera->GetGameObject() == nullptr) {
|
||||
return 0u;
|
||||
}
|
||||
|
||||
return state->plan->request.camera->GetGameObject()->GetUUID();
|
||||
}
|
||||
|
||||
mono_bool
|
||||
InternalCall_Rendering_RenderSceneSetupContext_GetIsConfigured(
|
||||
uint64_t nativeHandle) {
|
||||
@@ -5541,60 +5830,41 @@ InternalCall_Rendering_RenderSceneSetupContext_GetIsConfigured(
|
||||
: 0;
|
||||
}
|
||||
|
||||
mono_bool
|
||||
InternalCall_Rendering_RenderSceneSetupContext_UseDefaultSceneSetup(
|
||||
int32_t InternalCall_Rendering_RenderSceneSetupContext_GetClearFlags(
|
||||
uint64_t nativeHandle) {
|
||||
ManagedRenderSceneSetupContextState* const state =
|
||||
const ManagedRenderSceneSetupContextState* const state =
|
||||
FindManagedRenderSceneSetupContextState(nativeHandle);
|
||||
if (state == nullptr ||
|
||||
state->plan == nullptr ||
|
||||
state->sceneData == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Rendering::ApplyDefaultRenderPipelineSceneSetupPolicy(
|
||||
*state->plan,
|
||||
*state->sceneData);
|
||||
state->explicitlyConfigured = true;
|
||||
return 1;
|
||||
return state != nullptr &&
|
||||
state->plan != nullptr
|
||||
? static_cast<int32_t>(state->plan->request.clearFlags)
|
||||
: 0;
|
||||
}
|
||||
|
||||
mono_bool
|
||||
InternalCall_Rendering_RenderSceneSetupContext_UseDefaultEnvironment(
|
||||
InternalCall_Rendering_RenderSceneSetupContext_GetHasMainSceneDepthAttachment(
|
||||
uint64_t nativeHandle) {
|
||||
ManagedRenderSceneSetupContextState* const state =
|
||||
const ManagedRenderSceneSetupContextState* const state =
|
||||
FindManagedRenderSceneSetupContextState(nativeHandle);
|
||||
if (state == nullptr ||
|
||||
state->plan == nullptr ||
|
||||
state->sceneData == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
state->sceneData->environment =
|
||||
Rendering::BuildDefaultRenderPipelineEnvironmentData(
|
||||
*state->plan);
|
||||
state->explicitlyConfigured = true;
|
||||
return 1;
|
||||
return state != nullptr &&
|
||||
state->plan != nullptr &&
|
||||
state->plan->GetMainSceneSurface().GetDepthAttachment() != nullptr
|
||||
? 1
|
||||
: 0;
|
||||
}
|
||||
|
||||
mono_bool
|
||||
InternalCall_Rendering_RenderSceneSetupContext_UseDefaultGlobalShaderKeywords(
|
||||
InternalCall_Rendering_RenderSceneSetupContext_GetHasMainDirectionalShadow(
|
||||
uint64_t nativeHandle) {
|
||||
ManagedRenderSceneSetupContextState* const state =
|
||||
const ManagedRenderSceneSetupContextState* const state =
|
||||
FindManagedRenderSceneSetupContextState(nativeHandle);
|
||||
if (state == nullptr || state->sceneData == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
state->sceneData->globalShaderKeywords =
|
||||
Rendering::
|
||||
BuildDefaultRenderPipelineSceneGlobalShaderKeywords(
|
||||
*state->sceneData);
|
||||
state->explicitlyConfigured = true;
|
||||
return 1;
|
||||
return state != nullptr &&
|
||||
state->sceneData != nullptr &&
|
||||
state->sceneData->lighting.HasMainDirectionalShadow()
|
||||
? 1
|
||||
: 0;
|
||||
}
|
||||
|
||||
void InternalCall_Rendering_RenderSceneSetupContext_ClearEnvironment(
|
||||
void InternalCall_Rendering_RenderSceneSetupContext_SetEnvironmentNone(
|
||||
uint64_t nativeHandle) {
|
||||
ManagedRenderSceneSetupContextState* const state =
|
||||
FindManagedRenderSceneSetupContextState(nativeHandle);
|
||||
@@ -5606,6 +5876,56 @@ void InternalCall_Rendering_RenderSceneSetupContext_ClearEnvironment(
|
||||
state->explicitlyConfigured = true;
|
||||
}
|
||||
|
||||
mono_bool
|
||||
InternalCall_Rendering_RenderSceneSetupContext_UseCameraSkyboxMaterial(
|
||||
uint64_t nativeHandle) {
|
||||
ManagedRenderSceneSetupContextState* const state =
|
||||
FindManagedRenderSceneSetupContextState(nativeHandle);
|
||||
if (state == nullptr ||
|
||||
state->plan == nullptr ||
|
||||
state->sceneData == nullptr ||
|
||||
state->plan->request.camera == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const Resources::Material* skyboxMaterial =
|
||||
state->plan->request.camera->GetSkyboxMaterial();
|
||||
if (skyboxMaterial == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
state->sceneData->environment = {};
|
||||
state->sceneData->environment.mode =
|
||||
Rendering::RenderEnvironmentMode::MaterialSkybox;
|
||||
state->sceneData->environment.materialSkybox.material =
|
||||
skyboxMaterial;
|
||||
state->explicitlyConfigured = true;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void InternalCall_Rendering_RenderSceneSetupContext_SetProceduralSkybox(
|
||||
uint64_t nativeHandle,
|
||||
XCEngine::Math::Color* topColor,
|
||||
XCEngine::Math::Color* horizonColor,
|
||||
XCEngine::Math::Color* bottomColor) {
|
||||
ManagedRenderSceneSetupContextState* const state =
|
||||
FindManagedRenderSceneSetupContextState(nativeHandle);
|
||||
if (state == nullptr || state->sceneData == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
state->sceneData->environment = {};
|
||||
state->sceneData->environment.mode =
|
||||
Rendering::RenderEnvironmentMode::ProceduralSkybox;
|
||||
state->sceneData->environment.skybox.topColor =
|
||||
topColor != nullptr ? *topColor : XCEngine::Math::Color();
|
||||
state->sceneData->environment.skybox.horizonColor =
|
||||
horizonColor != nullptr ? *horizonColor : XCEngine::Math::Color();
|
||||
state->sceneData->environment.skybox.bottomColor =
|
||||
bottomColor != nullptr ? *bottomColor : XCEngine::Math::Color();
|
||||
state->explicitlyConfigured = true;
|
||||
}
|
||||
|
||||
void
|
||||
InternalCall_Rendering_RenderSceneSetupContext_ClearGlobalShaderKeywords(
|
||||
uint64_t nativeHandle) {
|
||||
@@ -5619,16 +5939,55 @@ InternalCall_Rendering_RenderSceneSetupContext_ClearGlobalShaderKeywords(
|
||||
state->explicitlyConfigured = true;
|
||||
}
|
||||
|
||||
void InternalCall_Rendering_RenderSceneSetupContext_ClearSceneSetup(
|
||||
uint64_t nativeHandle) {
|
||||
void InternalCall_Rendering_RenderSceneSetupContext_SetGlobalShaderKeyword(
|
||||
uint64_t nativeHandle,
|
||||
MonoString* keyword,
|
||||
mono_bool enabled) {
|
||||
ManagedRenderSceneSetupContextState* const state =
|
||||
FindManagedRenderSceneSetupContextState(nativeHandle);
|
||||
if (state == nullptr || state->sceneData == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
state->sceneData->environment = {};
|
||||
state->sceneData->globalShaderKeywords = {};
|
||||
const XCEngine::Containers::String normalizedKeyword =
|
||||
Resources::NormalizeShaderKeywordToken(
|
||||
XCEngine::Containers::String(
|
||||
MonoStringToUtf8(keyword).c_str()));
|
||||
if (normalizedKeyword.Empty()) {
|
||||
state->explicitlyConfigured = true;
|
||||
return;
|
||||
}
|
||||
|
||||
Resources::ShaderKeywordSet& keywordSet =
|
||||
state->sceneData->globalShaderKeywords;
|
||||
bool foundKeyword = false;
|
||||
size_t foundIndex = 0;
|
||||
for (size_t keywordIndex = 0;
|
||||
keywordIndex < keywordSet.enabledKeywords.Size();
|
||||
++keywordIndex) {
|
||||
if (keywordSet.enabledKeywords[keywordIndex] ==
|
||||
normalizedKeyword) {
|
||||
foundKeyword = true;
|
||||
foundIndex = keywordIndex;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (enabled != 0) {
|
||||
if (!foundKeyword) {
|
||||
keywordSet.enabledKeywords.PushBack(normalizedKeyword);
|
||||
}
|
||||
} else if (foundKeyword) {
|
||||
const size_t lastIndex =
|
||||
keywordSet.enabledKeywords.Size() - 1;
|
||||
if (foundIndex != lastIndex) {
|
||||
keywordSet.enabledKeywords[foundIndex] =
|
||||
keywordSet.enabledKeywords[lastIndex];
|
||||
}
|
||||
keywordSet.enabledKeywords.PopBack();
|
||||
}
|
||||
|
||||
Resources::NormalizeShaderKeywordSetInPlace(keywordSet);
|
||||
state->explicitlyConfigured = true;
|
||||
}
|
||||
|
||||
@@ -6024,6 +6383,18 @@ void RegisterInternalCalls() {
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Camera_SetDepth", reinterpret_cast<const void*>(&InternalCall_Camera_SetDepth));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Camera_GetPrimary", reinterpret_cast<const void*>(&InternalCall_Camera_GetPrimary));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Camera_SetPrimary", reinterpret_cast<const void*>(&InternalCall_Camera_SetPrimary));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Camera_GetClearMode", reinterpret_cast<const void*>(&InternalCall_Camera_GetClearMode));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Camera_SetClearMode", reinterpret_cast<const void*>(&InternalCall_Camera_SetClearMode));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Camera_GetStackType", reinterpret_cast<const void*>(&InternalCall_Camera_GetStackType));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Camera_SetStackType", reinterpret_cast<const void*>(&InternalCall_Camera_SetStackType));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Camera_GetProjectionType", reinterpret_cast<const void*>(&InternalCall_Camera_GetProjectionType));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Camera_GetSkyboxEnabled", reinterpret_cast<const void*>(&InternalCall_Camera_GetSkyboxEnabled));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Camera_GetHasSkyboxMaterial", reinterpret_cast<const void*>(&InternalCall_Camera_GetHasSkyboxMaterial));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Camera_GetHasFinalColorOverrides", reinterpret_cast<const void*>(&InternalCall_Camera_GetHasFinalColorOverrides));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Camera_GetFinalColorOverrideSettings", reinterpret_cast<const void*>(&InternalCall_Camera_GetFinalColorOverrideSettings));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Camera_GetSkyboxTopColor", reinterpret_cast<const void*>(&InternalCall_Camera_GetSkyboxTopColor));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Camera_GetSkyboxHorizonColor", reinterpret_cast<const void*>(&InternalCall_Camera_GetSkyboxHorizonColor));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Camera_GetSkyboxBottomColor", reinterpret_cast<const void*>(&InternalCall_Camera_GetSkyboxBottomColor));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Light_GetIntensity", reinterpret_cast<const void*>(&InternalCall_Light_GetIntensity));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Light_SetIntensity", reinterpret_cast<const void*>(&InternalCall_Light_SetIntensity));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Light_GetRange", reinterpret_cast<const void*>(&InternalCall_Light_GetRange));
|
||||
@@ -6076,7 +6447,10 @@ void RegisterInternalCalls() {
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_BeginRasterPass", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_BeginRasterPass));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_SetRasterPassSourceColorTexture", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_SetRasterPassSourceColorTexture));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_AddRasterPassReadTexture", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_AddRasterPassReadTexture));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_AddRasterPassReadDepthTexture", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_AddRasterPassReadDepthTexture));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_AddRasterPassTextureBinding", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_AddRasterPassTextureBinding));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_SetRasterPassColorAttachment", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_SetRasterPassColorAttachment));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_SetRasterPassDepthAttachment", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_SetRasterPassDepthAttachment));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_SetRasterPassColorScaleFullscreenExecution", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_SetRasterPassColorScaleFullscreenExecution));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_SetRasterPassShaderVectorFullscreenExecution", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_SetRasterPassShaderVectorFullscreenExecution));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Rendering_ScriptableRenderContext_SetRasterPassFinalColorFullscreenExecution", reinterpret_cast<const void*>(&InternalCall_Rendering_ScriptableRenderContext_SetRasterPassFinalColorFullscreenExecution));
|
||||
@@ -6158,14 +6532,21 @@ void RegisterInternalCalls() {
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Rendering_CameraRenderRequestContext_GetDirectionalShadowPlanningSettings", reinterpret_cast<const void*>(&InternalCall_Rendering_CameraRenderRequestContext_GetDirectionalShadowPlanningSettings));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Rendering_CameraRenderRequestContext_SetDirectionalShadowPlanningSettings", reinterpret_cast<const void*>(&InternalCall_Rendering_CameraRenderRequestContext_SetDirectionalShadowPlanningSettings));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Rendering_CameraRenderRequestContext_ClearDirectionalShadow", reinterpret_cast<const void*>(&InternalCall_Rendering_CameraRenderRequestContext_ClearDirectionalShadow));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Rendering_CameraRenderRequestContext_GetClearFlags", reinterpret_cast<const void*>(&InternalCall_Rendering_CameraRenderRequestContext_GetClearFlags));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Rendering_CameraRenderRequestContext_SetClearFlags", reinterpret_cast<const void*>(&InternalCall_Rendering_CameraRenderRequestContext_SetClearFlags));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Rendering_CameraRenderRequestContext_SetResolvedFinalColorPolicy", reinterpret_cast<const void*>(&InternalCall_Rendering_CameraRenderRequestContext_SetResolvedFinalColorPolicy));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Rendering_CameraRenderRequestContext_ClearFinalColorPolicy", reinterpret_cast<const void*>(&InternalCall_Rendering_CameraRenderRequestContext_ClearFinalColorPolicy));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Rendering_RenderSceneSetupContext_GetRendererIndex", reinterpret_cast<const void*>(&InternalCall_Rendering_RenderSceneSetupContext_GetRendererIndex));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Rendering_RenderSceneSetupContext_GetCameraGameObjectUUID", reinterpret_cast<const void*>(&InternalCall_Rendering_RenderSceneSetupContext_GetCameraGameObjectUUID));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Rendering_RenderSceneSetupContext_GetIsConfigured", reinterpret_cast<const void*>(&InternalCall_Rendering_RenderSceneSetupContext_GetIsConfigured));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Rendering_RenderSceneSetupContext_UseDefaultSceneSetup", reinterpret_cast<const void*>(&InternalCall_Rendering_RenderSceneSetupContext_UseDefaultSceneSetup));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Rendering_RenderSceneSetupContext_UseDefaultEnvironment", reinterpret_cast<const void*>(&InternalCall_Rendering_RenderSceneSetupContext_UseDefaultEnvironment));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Rendering_RenderSceneSetupContext_UseDefaultGlobalShaderKeywords", reinterpret_cast<const void*>(&InternalCall_Rendering_RenderSceneSetupContext_UseDefaultGlobalShaderKeywords));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Rendering_RenderSceneSetupContext_ClearEnvironment", reinterpret_cast<const void*>(&InternalCall_Rendering_RenderSceneSetupContext_ClearEnvironment));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Rendering_RenderSceneSetupContext_GetClearFlags", reinterpret_cast<const void*>(&InternalCall_Rendering_RenderSceneSetupContext_GetClearFlags));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Rendering_RenderSceneSetupContext_GetHasMainSceneDepthAttachment", reinterpret_cast<const void*>(&InternalCall_Rendering_RenderSceneSetupContext_GetHasMainSceneDepthAttachment));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Rendering_RenderSceneSetupContext_GetHasMainDirectionalShadow", reinterpret_cast<const void*>(&InternalCall_Rendering_RenderSceneSetupContext_GetHasMainDirectionalShadow));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Rendering_RenderSceneSetupContext_SetEnvironmentNone", reinterpret_cast<const void*>(&InternalCall_Rendering_RenderSceneSetupContext_SetEnvironmentNone));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Rendering_RenderSceneSetupContext_UseCameraSkyboxMaterial", reinterpret_cast<const void*>(&InternalCall_Rendering_RenderSceneSetupContext_UseCameraSkyboxMaterial));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Rendering_RenderSceneSetupContext_SetProceduralSkybox", reinterpret_cast<const void*>(&InternalCall_Rendering_RenderSceneSetupContext_SetProceduralSkybox));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Rendering_RenderSceneSetupContext_ClearGlobalShaderKeywords", reinterpret_cast<const void*>(&InternalCall_Rendering_RenderSceneSetupContext_ClearGlobalShaderKeywords));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Rendering_RenderSceneSetupContext_ClearSceneSetup", reinterpret_cast<const void*>(&InternalCall_Rendering_RenderSceneSetupContext_ClearSceneSetup));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Rendering_RenderSceneSetupContext_SetGlobalShaderKeyword", reinterpret_cast<const void*>(&InternalCall_Rendering_RenderSceneSetupContext_SetGlobalShaderKeyword));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Rendering_DirectionalShadowExecutionContext_GetHasPlannedMainDirectionalShadow", reinterpret_cast<const void*>(&InternalCall_Rendering_DirectionalShadowExecutionContext_GetHasPlannedMainDirectionalShadow));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Rendering_DirectionalShadowExecutionContext_GetRendererIndex", reinterpret_cast<const void*>(&InternalCall_Rendering_DirectionalShadowExecutionContext_GetRendererIndex));
|
||||
mono_add_internal_call("XCEngine.InternalCalls::Rendering_DirectionalShadowExecutionContext_GetIsConfigured", reinterpret_cast<const void*>(&InternalCall_Rendering_DirectionalShadowExecutionContext_GetIsConfigured));
|
||||
|
||||
@@ -144,6 +144,9 @@ set(XCENGINE_SCRIPT_CORE_SOURCES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/AssemblyInfo.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Behaviour.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Camera.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/CameraClearMode.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/CameraProjectionType.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/CameraStackType.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Color.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Component.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Debug.cs
|
||||
@@ -180,13 +183,16 @@ set(XCENGINE_SCRIPT_CORE_SOURCES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Rendering/Core/DirectionalShadowPlanningSettings.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Rendering/Core/DrawingSettings.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Rendering/Core/FinalColorExposureMode.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Rendering/Core/FinalColorOverrideSettings.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Rendering/Core/FinalColorOutputTransferMode.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Rendering/Core/FinalColorSettings.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Rendering/Core/FinalColorToneMappingMode.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Rendering/Core/FilteringSettings.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Rendering/Core/GraphicsSettings.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Rendering/Core/NativeSceneFeaturePassId.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Rendering/Core/RenderSceneSetupContext.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Rendering/Core/RenderPipelineAsset.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Rendering/Core/RenderClearFlags.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Rendering/Core/RenderQueueRange.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Rendering/Core/RenderStateBlock.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.ScriptCore/Rendering/Core/RenderStateMask.cs
|
||||
@@ -212,6 +218,7 @@ set(XCENGINE_SCRIPT_CORE_SOURCES
|
||||
set(XCENGINE_RENDER_PIPELINES_UNIVERSAL_SOURCES
|
||||
# Universal renderer package
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/CameraData.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/ColorScalePostProcessSettings.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/ColorScalePostProcessRendererFeature.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/BuiltinFinalColorPass.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/BuiltinGaussianSplatRendererFeature.cs
|
||||
@@ -226,12 +233,14 @@ set(XCENGINE_RENDER_PIPELINES_UNIVERSAL_SOURCES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/EnvironmentData.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/FinalColorData.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/LightingData.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/RenderClearFlags.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/RenderEnvironmentMode.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/RenderObjectsFeatureSettings.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/RenderPassEvent.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/RenderObjectsRendererFeature.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/RendererBlock.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/RendererBackedRenderPipeline.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/RendererBackedRenderPipelineAsset.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/RendererBlocks.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/RendererCameraRequestContext.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/RendererDrivenRenderPipeline.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/RendererRecordingContext.cs
|
||||
@@ -242,15 +251,27 @@ set(XCENGINE_RENDER_PIPELINES_UNIVERSAL_SOURCES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/ScriptableRenderPass.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/ScriptableRenderer.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/ScriptableRendererData.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/ScriptableRendererDataCollection.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/ScriptableRendererFeatureCollection.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/ScriptableRendererFeature.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/StageColorData.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalAdditionalCameraData.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalDefaultRendererFeatureFactory.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalFinalColorSettings.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalFinalOutputBlock.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalMainSceneData.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalMainSceneBlock.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalMainSceneFeatureUtility.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalNativeSceneFeatureController.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalColorScalePostProcessController.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalDepthPrepassBlock.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalPostProcessBlock.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalRenderObjectsFeatureController.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalRenderPipeline.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalRenderer.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalRendererData.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalRenderPipelineAsset.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalShadowCasterBlock.cs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/XCEngine.RenderPipelines.Universal/Rendering/Universal/UniversalShadowSettings.cs
|
||||
)
|
||||
|
||||
|
||||
@@ -59,6 +59,80 @@ namespace Gameplay
|
||||
}
|
||||
}
|
||||
|
||||
internal static class ProbeScriptableObjectFactory
|
||||
{
|
||||
public static T Create<T>()
|
||||
where T : ScriptableObject
|
||||
{
|
||||
T instance =
|
||||
ScriptableObject.CreateInstance<T>();
|
||||
if (instance != null)
|
||||
{
|
||||
return instance;
|
||||
}
|
||||
|
||||
throw new InvalidOperationException(
|
||||
"Failed to create ScriptableObject probe instance: " +
|
||||
typeof(T).FullName);
|
||||
}
|
||||
|
||||
public static ScriptableRendererData[] CreateRendererDataList(
|
||||
params ScriptableRendererData[] rendererData)
|
||||
{
|
||||
return Compact(rendererData);
|
||||
}
|
||||
|
||||
public static ScriptableRendererFeature[] CreateRendererFeatureList(
|
||||
params ScriptableRendererFeature[] rendererFeatures)
|
||||
{
|
||||
return Compact(rendererFeatures);
|
||||
}
|
||||
|
||||
private static T[] Compact<T>(
|
||||
params T[] items)
|
||||
where T : class
|
||||
{
|
||||
if (items == null ||
|
||||
items.Length == 0)
|
||||
{
|
||||
return Array.Empty<T>();
|
||||
}
|
||||
|
||||
int validCount = 0;
|
||||
for (int i = 0; i < items.Length; ++i)
|
||||
{
|
||||
if (items[i] != null)
|
||||
{
|
||||
validCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if (validCount == items.Length)
|
||||
{
|
||||
return items;
|
||||
}
|
||||
|
||||
if (validCount == 0)
|
||||
{
|
||||
return Array.Empty<T>();
|
||||
}
|
||||
|
||||
T[] compactItems = new T[validCount];
|
||||
int writeIndex = 0;
|
||||
for (int i = 0; i < items.Length; ++i)
|
||||
{
|
||||
if (items[i] == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
compactItems[writeIndex++] = items[i];
|
||||
}
|
||||
|
||||
return compactItems;
|
||||
}
|
||||
}
|
||||
|
||||
internal enum SceneInjectionKind
|
||||
{
|
||||
BeforeOpaque,
|
||||
@@ -345,6 +419,84 @@ namespace Gameplay
|
||||
renderer.EnqueuePass(renderPass);
|
||||
}
|
||||
}
|
||||
|
||||
public override void ConfigureCameraFramePlan(
|
||||
ScriptableRenderPipelinePlanningContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bool hasPostProcessPass = false;
|
||||
bool hasFinalOutputPass = false;
|
||||
for (int i = 0; i < m_passes.Length; ++i)
|
||||
{
|
||||
ScriptableRenderPass renderPass = m_passes[i];
|
||||
if (renderPass == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (renderPass.SupportsStage(
|
||||
CameraFrameStage.PostProcess))
|
||||
{
|
||||
hasPostProcessPass = true;
|
||||
}
|
||||
|
||||
if (renderPass.SupportsStage(
|
||||
CameraFrameStage.FinalOutput))
|
||||
{
|
||||
hasFinalOutputPass = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool needsGraphManagedPostProcessOutput =
|
||||
context.HasFinalColorProcessing() ||
|
||||
context.IsStageRequested(
|
||||
CameraFrameStage.FinalOutput) ||
|
||||
hasFinalOutputPass;
|
||||
|
||||
if (hasPostProcessPass)
|
||||
{
|
||||
if (!context.IsStageRequested(
|
||||
CameraFrameStage.PostProcess))
|
||||
{
|
||||
context.RequestFullscreenStage(
|
||||
CameraFrameStage.PostProcess,
|
||||
CameraFrameColorSource.MainSceneColor,
|
||||
needsGraphManagedPostProcessOutput);
|
||||
}
|
||||
else if (needsGraphManagedPostProcessOutput &&
|
||||
context.GetStageColorSource(
|
||||
CameraFrameStage.PostProcess) !=
|
||||
CameraFrameColorSource.ExplicitSurface &&
|
||||
!context.UsesGraphManagedOutputColor(
|
||||
CameraFrameStage.PostProcess))
|
||||
{
|
||||
CameraFrameColorSource source =
|
||||
context.GetStageColorSource(
|
||||
CameraFrameStage.PostProcess);
|
||||
context.ClearFullscreenStage(
|
||||
CameraFrameStage.PostProcess);
|
||||
context.RequestFullscreenStage(
|
||||
CameraFrameStage.PostProcess,
|
||||
source,
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
||||
if (hasFinalOutputPass &&
|
||||
!context.IsStageRequested(
|
||||
CameraFrameStage.FinalOutput))
|
||||
{
|
||||
context.RequestFullscreenStage(
|
||||
CameraFrameStage.FinalOutput,
|
||||
hasPostProcessPass
|
||||
? CameraFrameColorSource.PostProcessColor
|
||||
: CameraFrameColorSource.MainSceneColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class ProbeSceneRenderer : ScriptableRenderer
|
||||
@@ -484,13 +636,26 @@ namespace Gameplay
|
||||
internal sealed class ManagedFeaturePassOrderCustomFeature
|
||||
: ScriptableRendererFeature
|
||||
{
|
||||
private readonly ManagedFeaturePassOrderProbePass m_pass;
|
||||
private ManagedFeaturePassOrderProbePass m_pass;
|
||||
|
||||
public ManagedFeaturePassOrderCustomFeature(
|
||||
string token)
|
||||
public string token = string.Empty;
|
||||
|
||||
protected override int ComputeRuntimeStateHash()
|
||||
{
|
||||
int hash =
|
||||
base.ComputeRuntimeStateHash();
|
||||
hash =
|
||||
RuntimeStateHashUtility.Combine(
|
||||
hash,
|
||||
token ?? string.Empty);
|
||||
return hash;
|
||||
}
|
||||
|
||||
public override void Create()
|
||||
{
|
||||
m_pass =
|
||||
new ManagedFeaturePassOrderProbePass(token);
|
||||
new ManagedFeaturePassOrderProbePass(
|
||||
token ?? string.Empty);
|
||||
}
|
||||
|
||||
public override void AddRenderPasses(
|
||||
@@ -504,7 +669,11 @@ namespace Gameplay
|
||||
return;
|
||||
}
|
||||
|
||||
renderer.EnqueuePass(m_pass);
|
||||
CreateInstance();
|
||||
if (m_pass != null)
|
||||
{
|
||||
renderer.EnqueuePass(m_pass);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -524,11 +693,19 @@ namespace Gameplay
|
||||
public ManagedFeaturePassOrderProbeRendererData()
|
||||
: base(false)
|
||||
{
|
||||
rendererFeatures = new ScriptableRendererFeature[]
|
||||
{
|
||||
new ManagedFeaturePassOrderCustomFeature("CustomA"),
|
||||
new ManagedFeaturePassOrderCustomFeature("CustomB")
|
||||
};
|
||||
ManagedFeaturePassOrderCustomFeature customA =
|
||||
ProbeScriptableObjectFactory
|
||||
.Create<ManagedFeaturePassOrderCustomFeature>();
|
||||
ManagedFeaturePassOrderCustomFeature customB =
|
||||
ProbeScriptableObjectFactory
|
||||
.Create<ManagedFeaturePassOrderCustomFeature>();
|
||||
customA.token = "CustomA";
|
||||
customB.token = "CustomB";
|
||||
rendererFeatures =
|
||||
ProbeScriptableObjectFactory
|
||||
.CreateRendererFeatureList(
|
||||
customA,
|
||||
customB);
|
||||
}
|
||||
|
||||
protected override ScriptableRenderer CreateProbeRenderer()
|
||||
@@ -1018,18 +1195,13 @@ namespace Gameplay
|
||||
internal sealed class ManagedUniversalRenderPipelineProbeRendererData
|
||||
: ProbeRendererData
|
||||
{
|
||||
private readonly Vector4 m_postProcessScale;
|
||||
|
||||
public ManagedUniversalRenderPipelineProbeRendererData(
|
||||
Vector4 postProcessScale)
|
||||
{
|
||||
m_postProcessScale = postProcessScale;
|
||||
}
|
||||
public Vector4 postProcessScale =
|
||||
new Vector4(1.03f, 0.98f, 0.94f, 1.0f);
|
||||
|
||||
protected override ScriptableRenderer CreateProbeRenderer()
|
||||
{
|
||||
return new ManagedUniversalRenderPipelineProbe(
|
||||
m_postProcessScale);
|
||||
postProcessScale);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1126,10 +1298,11 @@ namespace Gameplay
|
||||
: base(false)
|
||||
{
|
||||
ManagedRendererInvalidationProbeState.CreateFeatureCallCount++;
|
||||
rendererFeatures = new ScriptableRendererFeature[]
|
||||
{
|
||||
new ManagedRendererInvalidationProbeFeature()
|
||||
};
|
||||
rendererFeatures =
|
||||
ProbeScriptableObjectFactory
|
||||
.CreateRendererFeatureList(
|
||||
ProbeScriptableObjectFactory
|
||||
.Create<ManagedRendererInvalidationProbeFeature>());
|
||||
}
|
||||
|
||||
protected override ScriptableRenderer CreateProbeRenderer()
|
||||
@@ -1205,11 +1378,12 @@ namespace Gameplay
|
||||
: base(false)
|
||||
{
|
||||
m_feature =
|
||||
new ManagedPersistentFeatureProbeRendererFeature();
|
||||
rendererFeatures = new ScriptableRendererFeature[]
|
||||
{
|
||||
m_feature
|
||||
};
|
||||
ProbeScriptableObjectFactory
|
||||
.Create<ManagedPersistentFeatureProbeRendererFeature>();
|
||||
rendererFeatures =
|
||||
ProbeScriptableObjectFactory
|
||||
.CreateRendererFeatureList(
|
||||
m_feature);
|
||||
}
|
||||
|
||||
protected override ScriptableRenderer CreateProbeRenderer()
|
||||
@@ -1260,10 +1434,11 @@ namespace Gameplay
|
||||
public ManagedFeaturePlannedPostProcessRendererData()
|
||||
: base(false)
|
||||
{
|
||||
rendererFeatures = new ScriptableRendererFeature[]
|
||||
{
|
||||
new ManagedFeaturePlannedPostProcessRendererFeature()
|
||||
};
|
||||
rendererFeatures =
|
||||
ProbeScriptableObjectFactory
|
||||
.CreateRendererFeatureList(
|
||||
ProbeScriptableObjectFactory
|
||||
.Create<ManagedFeaturePlannedPostProcessRendererFeature>());
|
||||
}
|
||||
|
||||
protected override ScriptableRenderer CreateProbeRenderer()
|
||||
@@ -1354,10 +1529,11 @@ namespace Gameplay
|
||||
: base(false)
|
||||
{
|
||||
ManagedLifecycleProbeState.CreateFeatureCallCount++;
|
||||
rendererFeatures = new ScriptableRendererFeature[]
|
||||
{
|
||||
new ManagedLifecycleProbeRendererFeature()
|
||||
};
|
||||
rendererFeatures =
|
||||
ProbeScriptableObjectFactory
|
||||
.CreateRendererFeatureList(
|
||||
ProbeScriptableObjectFactory
|
||||
.Create<ManagedLifecycleProbeRendererFeature>());
|
||||
}
|
||||
|
||||
protected override ScriptableRenderer CreateProbeRenderer()
|
||||
@@ -1427,10 +1603,11 @@ namespace Gameplay
|
||||
{
|
||||
public ManagedUniversalLifecycleProbeAsset()
|
||||
{
|
||||
rendererDataList = new ScriptableRendererData[]
|
||||
{
|
||||
new ManagedLifecycleProbeRendererData()
|
||||
};
|
||||
rendererDataList =
|
||||
ProbeScriptableObjectFactory
|
||||
.CreateRendererDataList(
|
||||
ProbeScriptableObjectFactory
|
||||
.Create<ManagedLifecycleProbeRendererData>());
|
||||
}
|
||||
|
||||
protected override ScriptableRenderPipeline CreatePipeline()
|
||||
@@ -1453,10 +1630,11 @@ namespace Gameplay
|
||||
|
||||
public ManagedRenderPipelineProbeAsset()
|
||||
{
|
||||
rendererDataList = new ScriptableRendererData[]
|
||||
{
|
||||
new ManagedRenderPipelineProbeRendererData()
|
||||
};
|
||||
rendererDataList =
|
||||
ProbeScriptableObjectFactory
|
||||
.CreateRendererDataList(
|
||||
ProbeScriptableObjectFactory
|
||||
.Create<ManagedRenderPipelineProbeRendererData>());
|
||||
}
|
||||
|
||||
protected override ScriptableRenderPipeline CreatePipeline()
|
||||
@@ -1472,10 +1650,10 @@ namespace Gameplay
|
||||
public ManagedPostProcessRenderPipelineProbeAsset()
|
||||
{
|
||||
rendererDataList =
|
||||
new ScriptableRendererData[]
|
||||
{
|
||||
new ManagedPostProcessRenderPipelineProbeRendererData()
|
||||
};
|
||||
ProbeScriptableObjectFactory
|
||||
.CreateRendererDataList(
|
||||
ProbeScriptableObjectFactory
|
||||
.Create<ManagedPostProcessRenderPipelineProbeRendererData>());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1499,11 +1677,14 @@ namespace Gameplay
|
||||
|
||||
private ScriptableRendererData[] CreateRendererDataList()
|
||||
{
|
||||
return new ScriptableRendererData[]
|
||||
{
|
||||
new ManagedUniversalRenderPipelineProbeRendererData(
|
||||
postProcessScale)
|
||||
};
|
||||
ManagedUniversalRenderPipelineProbeRendererData rendererData =
|
||||
ProbeScriptableObjectFactory
|
||||
.Create<ManagedUniversalRenderPipelineProbeRendererData>();
|
||||
rendererData.postProcessScale =
|
||||
postProcessScale;
|
||||
return ProbeScriptableObjectFactory
|
||||
.CreateRendererDataList(
|
||||
rendererData);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1514,10 +1695,11 @@ namespace Gameplay
|
||||
{
|
||||
ManagedRendererReuseProbeRendererData.CreateRendererCallCount = 0;
|
||||
ManagedRendererReuseProbeRendererData.SetupRendererCallCount = 0;
|
||||
rendererDataList = new ScriptableRendererData[]
|
||||
{
|
||||
new ManagedRendererReuseProbeRendererData()
|
||||
};
|
||||
rendererDataList =
|
||||
ProbeScriptableObjectFactory
|
||||
.CreateRendererDataList(
|
||||
ProbeScriptableObjectFactory
|
||||
.Create<ManagedRendererReuseProbeRendererData>());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1530,11 +1712,13 @@ namespace Gameplay
|
||||
public ManagedRendererInvalidationProbeAsset()
|
||||
{
|
||||
ManagedRendererInvalidationProbeState.Reset();
|
||||
m_rendererData = new ManagedRendererInvalidationProbeRendererData();
|
||||
rendererDataList = new ScriptableRendererData[]
|
||||
{
|
||||
m_rendererData
|
||||
};
|
||||
m_rendererData =
|
||||
ProbeScriptableObjectFactory
|
||||
.Create<ManagedRendererInvalidationProbeRendererData>();
|
||||
rendererDataList =
|
||||
ProbeScriptableObjectFactory
|
||||
.CreateRendererDataList(
|
||||
m_rendererData);
|
||||
}
|
||||
|
||||
protected override ScriptableRenderPipeline
|
||||
@@ -1565,11 +1749,12 @@ namespace Gameplay
|
||||
{
|
||||
ManagedPersistentFeatureProbeState.Reset();
|
||||
m_rendererData =
|
||||
new ManagedPersistentFeatureProbeRendererData();
|
||||
rendererDataList = new ScriptableRendererData[]
|
||||
{
|
||||
m_rendererData
|
||||
};
|
||||
ProbeScriptableObjectFactory
|
||||
.Create<ManagedPersistentFeatureProbeRendererData>();
|
||||
rendererDataList =
|
||||
ProbeScriptableObjectFactory
|
||||
.CreateRendererDataList(
|
||||
m_rendererData);
|
||||
}
|
||||
|
||||
public void InvalidateDefaultRendererForTest()
|
||||
@@ -1589,10 +1774,11 @@ namespace Gameplay
|
||||
public ManagedFeaturePassOrderProbeAsset()
|
||||
{
|
||||
ManagedFeaturePassOrderProbeState.Reset();
|
||||
rendererDataList = new ScriptableRendererData[]
|
||||
{
|
||||
new ManagedFeaturePassOrderProbeRendererData()
|
||||
};
|
||||
rendererDataList =
|
||||
ProbeScriptableObjectFactory
|
||||
.CreateRendererDataList(
|
||||
ProbeScriptableObjectFactory
|
||||
.Create<ManagedFeaturePassOrderProbeRendererData>());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1684,10 +1870,10 @@ namespace Gameplay
|
||||
public ManagedPlannedFullscreenRenderPipelineProbeAsset()
|
||||
{
|
||||
rendererDataList =
|
||||
new ScriptableRendererData[]
|
||||
{
|
||||
new ManagedPlannedFullscreenRenderPipelineProbeRendererData()
|
||||
};
|
||||
ProbeScriptableObjectFactory
|
||||
.CreateRendererDataList(
|
||||
ProbeScriptableObjectFactory
|
||||
.Create<ManagedPlannedFullscreenRenderPipelineProbeRendererData>());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1697,10 +1883,10 @@ namespace Gameplay
|
||||
public ManagedFeaturePlannedPostProcessProbeAsset()
|
||||
{
|
||||
rendererDataList =
|
||||
new ScriptableRendererData[]
|
||||
{
|
||||
new ManagedFeaturePlannedPostProcessRendererData()
|
||||
};
|
||||
ProbeScriptableObjectFactory
|
||||
.CreateRendererDataList(
|
||||
ProbeScriptableObjectFactory
|
||||
.Create<ManagedFeaturePlannedPostProcessRendererData>());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1710,10 +1896,10 @@ namespace Gameplay
|
||||
public ManagedClearedPostProcessRenderPipelineProbeAsset()
|
||||
{
|
||||
rendererDataList =
|
||||
new ScriptableRendererData[]
|
||||
{
|
||||
new ManagedPlannedFullscreenRenderPipelineProbeRendererData()
|
||||
};
|
||||
ProbeScriptableObjectFactory
|
||||
.CreateRendererDataList(
|
||||
ProbeScriptableObjectFactory
|
||||
.Create<ManagedPlannedFullscreenRenderPipelineProbeRendererData>());
|
||||
}
|
||||
|
||||
protected override void ConfigureCameraFramePlan(
|
||||
@@ -1760,10 +1946,11 @@ namespace Gameplay
|
||||
{
|
||||
public ManagedCameraRequestConfiguredRenderPipelineProbeAsset()
|
||||
{
|
||||
rendererDataList = new ScriptableRendererData[]
|
||||
{
|
||||
new ManagedCameraRequestConfiguredRendererData()
|
||||
};
|
||||
rendererDataList =
|
||||
ProbeScriptableObjectFactory
|
||||
.CreateRendererDataList(
|
||||
ProbeScriptableObjectFactory
|
||||
.Create<ManagedCameraRequestConfiguredRendererData>());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1773,10 +1960,10 @@ namespace Gameplay
|
||||
public ManagedRenderContextCameraDataProbeAsset()
|
||||
{
|
||||
rendererDataList =
|
||||
new ScriptableRendererData[]
|
||||
{
|
||||
new ManagedRenderContextCameraDataProbeRendererData()
|
||||
};
|
||||
ProbeScriptableObjectFactory
|
||||
.CreateRendererDataList(
|
||||
ProbeScriptableObjectFactory
|
||||
.Create<ManagedRenderContextCameraDataProbeRendererData>());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1785,10 +1972,11 @@ namespace Gameplay
|
||||
{
|
||||
public ManagedFinalColorRenderPipelineProbeAsset()
|
||||
{
|
||||
rendererDataList = new ScriptableRendererData[]
|
||||
{
|
||||
new ManagedRenderPipelineProbeRendererData()
|
||||
};
|
||||
rendererDataList =
|
||||
ProbeScriptableObjectFactory
|
||||
.CreateRendererDataList(
|
||||
ProbeScriptableObjectFactory
|
||||
.Create<ManagedRenderPipelineProbeRendererData>());
|
||||
}
|
||||
|
||||
protected override FinalColorSettings GetDefaultFinalColorSettings()
|
||||
@@ -1803,10 +1991,10 @@ namespace Gameplay
|
||||
public ManagedRenderContextFinalColorDataProbeAsset()
|
||||
{
|
||||
rendererDataList =
|
||||
new ScriptableRendererData[]
|
||||
{
|
||||
new ManagedRenderContextCameraDataProbeRendererData()
|
||||
};
|
||||
ProbeScriptableObjectFactory
|
||||
.CreateRendererDataList(
|
||||
ProbeScriptableObjectFactory
|
||||
.Create<ManagedRenderContextCameraDataProbeRendererData>());
|
||||
}
|
||||
|
||||
protected override FinalColorSettings GetDefaultFinalColorSettings()
|
||||
@@ -1821,10 +2009,10 @@ namespace Gameplay
|
||||
public ManagedRenderContextStageColorDataProbeAsset()
|
||||
{
|
||||
rendererDataList =
|
||||
new ScriptableRendererData[]
|
||||
{
|
||||
new ManagedRenderContextStageColorDataProbeRendererData()
|
||||
};
|
||||
ProbeScriptableObjectFactory
|
||||
.CreateRendererDataList(
|
||||
ProbeScriptableObjectFactory
|
||||
.Create<ManagedRenderContextStageColorDataProbeRendererData>());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1966,7 +2154,8 @@ namespace Gameplay
|
||||
public void Start()
|
||||
{
|
||||
GraphicsSettings.renderPipelineAsset =
|
||||
new ManagedRendererInvalidationProbeAsset();
|
||||
ProbeScriptableObjectFactory
|
||||
.Create<ManagedRendererInvalidationProbeAsset>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2035,7 +2224,8 @@ namespace Gameplay
|
||||
public void Start()
|
||||
{
|
||||
GraphicsSettings.renderPipelineAsset =
|
||||
new ManagedPersistentFeatureProbeAsset();
|
||||
ProbeScriptableObjectFactory
|
||||
.Create<ManagedPersistentFeatureProbeAsset>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2088,7 +2278,8 @@ namespace Gameplay
|
||||
public void Start()
|
||||
{
|
||||
GraphicsSettings.renderPipelineAsset =
|
||||
new ManagedFeaturePassOrderProbeAsset();
|
||||
ProbeScriptableObjectFactory
|
||||
.Create<ManagedFeaturePassOrderProbeAsset>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2111,7 +2302,8 @@ namespace Gameplay
|
||||
public void Start()
|
||||
{
|
||||
GraphicsSettings.renderPipelineAsset =
|
||||
new ManagedAssetInvalidationProbeAsset();
|
||||
ProbeScriptableObjectFactory
|
||||
.Create<ManagedAssetInvalidationProbeAsset>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2193,7 +2385,8 @@ namespace Gameplay
|
||||
ManagedRendererReuseProbeRendererData.CreateRendererCallCount = 0;
|
||||
ManagedRendererReuseProbeRendererData.SetupRendererCallCount = 0;
|
||||
GraphicsSettings.renderPipelineAsset =
|
||||
new ManagedRenderPipelineProbeAsset();
|
||||
ProbeScriptableObjectFactory
|
||||
.Create<ManagedRenderPipelineProbeAsset>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2273,7 +2466,8 @@ namespace Gameplay
|
||||
{
|
||||
ManagedLifecycleProbeState.Reset();
|
||||
GraphicsSettings.renderPipelineAsset =
|
||||
new ManagedUniversalLifecycleProbeAsset();
|
||||
ProbeScriptableObjectFactory
|
||||
.Create<ManagedUniversalLifecycleProbeAsset>();
|
||||
}
|
||||
|
||||
public void Update()
|
||||
@@ -2525,11 +2719,13 @@ namespace Gameplay
|
||||
ManagedUniversalRenderPipelineProbe.RecordPostProcessCallCount = 0;
|
||||
ManagedUniversalRenderPipelineProbe.LastPostProcessScale =
|
||||
new Vector4(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
ManagedUniversalRenderPipelineProbeAsset asset =
|
||||
ProbeScriptableObjectFactory
|
||||
.Create<ManagedUniversalRenderPipelineProbeAsset>();
|
||||
asset.postProcessScale =
|
||||
new Vector4(1.11f, 0.97f, 0.93f, 1.0f);
|
||||
GraphicsSettings.renderPipelineAsset =
|
||||
new ManagedUniversalRenderPipelineProbeAsset
|
||||
{
|
||||
postProcessScale = new Vector4(1.11f, 0.97f, 0.93f, 1.0f)
|
||||
};
|
||||
asset;
|
||||
}
|
||||
|
||||
public void Update()
|
||||
@@ -2583,7 +2779,8 @@ namespace Gameplay
|
||||
{
|
||||
CameraDataObservationPass.Reset();
|
||||
GraphicsSettings.renderPipelineAsset =
|
||||
new ManagedRenderContextCameraDataProbeAsset();
|
||||
ProbeScriptableObjectFactory
|
||||
.Create<ManagedRenderContextCameraDataProbeAsset>();
|
||||
}
|
||||
|
||||
public void Update()
|
||||
@@ -2655,7 +2852,8 @@ namespace Gameplay
|
||||
{
|
||||
CameraDataObservationPass.Reset();
|
||||
GraphicsSettings.renderPipelineAsset =
|
||||
new ManagedRenderContextCameraDataProbeAsset();
|
||||
ProbeScriptableObjectFactory
|
||||
.Create<ManagedRenderContextCameraDataProbeAsset>();
|
||||
}
|
||||
|
||||
public void Update()
|
||||
@@ -2699,7 +2897,8 @@ namespace Gameplay
|
||||
{
|
||||
CameraDataObservationPass.Reset();
|
||||
GraphicsSettings.renderPipelineAsset =
|
||||
new ManagedRenderContextCameraDataProbeAsset();
|
||||
ProbeScriptableObjectFactory
|
||||
.Create<ManagedRenderContextCameraDataProbeAsset>();
|
||||
}
|
||||
|
||||
public void Update()
|
||||
@@ -2742,7 +2941,8 @@ namespace Gameplay
|
||||
{
|
||||
CameraDataObservationPass.Reset();
|
||||
GraphicsSettings.renderPipelineAsset =
|
||||
new ManagedRenderContextCameraDataProbeAsset();
|
||||
ProbeScriptableObjectFactory
|
||||
.Create<ManagedRenderContextCameraDataProbeAsset>();
|
||||
}
|
||||
|
||||
public void Update()
|
||||
@@ -2816,7 +3016,8 @@ namespace Gameplay
|
||||
{
|
||||
CameraDataObservationPass.Reset();
|
||||
GraphicsSettings.renderPipelineAsset =
|
||||
new ManagedRenderContextFinalColorDataProbeAsset();
|
||||
ProbeScriptableObjectFactory
|
||||
.Create<ManagedRenderContextFinalColorDataProbeAsset>();
|
||||
}
|
||||
|
||||
public void Update()
|
||||
@@ -2867,7 +3068,8 @@ namespace Gameplay
|
||||
{
|
||||
StageColorObservationPass.Reset();
|
||||
GraphicsSettings.renderPipelineAsset =
|
||||
new ManagedRenderContextStageColorDataProbeAsset();
|
||||
ProbeScriptableObjectFactory
|
||||
.Create<ManagedRenderContextStageColorDataProbeAsset>();
|
||||
}
|
||||
|
||||
public void Update()
|
||||
|
||||
@@ -8,40 +8,41 @@ namespace XCEngine.Rendering.Universal
|
||||
{
|
||||
public RenderPassEvent passEvent =
|
||||
RenderPassEvent.BeforeRenderingTransparents;
|
||||
|
||||
private NativeSceneFeaturePass m_pass;
|
||||
private readonly UniversalNativeSceneFeatureController m_controller =
|
||||
new UniversalNativeSceneFeatureController(
|
||||
NativeSceneFeaturePassId
|
||||
.BuiltinGaussianSplat);
|
||||
|
||||
protected override int ComputeRuntimeStateHash()
|
||||
{
|
||||
int hash =
|
||||
base.ComputeRuntimeStateHash();
|
||||
hash =
|
||||
RuntimeStateHashUtility.Combine(
|
||||
hash,
|
||||
(int)passEvent);
|
||||
return hash;
|
||||
return m_controller.AppendRuntimeStateHash(
|
||||
hash,
|
||||
passEvent);
|
||||
}
|
||||
|
||||
public override void Create()
|
||||
{
|
||||
m_pass = new NativeSceneFeaturePass(
|
||||
"BuiltinGaussianSplatPass",
|
||||
passEvent);
|
||||
m_controller.Create(passEvent);
|
||||
}
|
||||
|
||||
public override void AddRenderPasses(
|
||||
ScriptableRenderer renderer,
|
||||
RenderingData renderingData)
|
||||
{
|
||||
if (renderer == null)
|
||||
if (renderer == null ||
|
||||
renderingData == null ||
|
||||
!renderingData.isMainSceneStage)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CreateInstance();
|
||||
|
||||
m_pass.Configure(passEvent);
|
||||
renderer.EnqueuePass(m_pass);
|
||||
m_controller.EnqueuePass(
|
||||
renderer,
|
||||
renderingData,
|
||||
passEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,40 +8,41 @@ namespace XCEngine.Rendering.Universal
|
||||
{
|
||||
public RenderPassEvent passEvent =
|
||||
RenderPassEvent.BeforeRenderingTransparents;
|
||||
|
||||
private NativeSceneFeaturePass m_pass;
|
||||
private readonly UniversalNativeSceneFeatureController m_controller =
|
||||
new UniversalNativeSceneFeatureController(
|
||||
NativeSceneFeaturePassId
|
||||
.BuiltinVolumetric);
|
||||
|
||||
protected override int ComputeRuntimeStateHash()
|
||||
{
|
||||
int hash =
|
||||
base.ComputeRuntimeStateHash();
|
||||
hash =
|
||||
RuntimeStateHashUtility.Combine(
|
||||
hash,
|
||||
(int)passEvent);
|
||||
return hash;
|
||||
return m_controller.AppendRuntimeStateHash(
|
||||
hash,
|
||||
passEvent);
|
||||
}
|
||||
|
||||
public override void Create()
|
||||
{
|
||||
m_pass = new NativeSceneFeaturePass(
|
||||
"BuiltinVolumetricPass",
|
||||
passEvent);
|
||||
m_controller.Create(passEvent);
|
||||
}
|
||||
|
||||
public override void AddRenderPasses(
|
||||
ScriptableRenderer renderer,
|
||||
RenderingData renderingData)
|
||||
{
|
||||
if (renderer == null)
|
||||
if (renderer == null ||
|
||||
renderingData == null ||
|
||||
!renderingData.isMainSceneStage)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CreateInstance();
|
||||
|
||||
m_pass.Configure(passEvent);
|
||||
renderer.EnqueuePass(m_pass);
|
||||
m_controller.EnqueuePass(
|
||||
renderer,
|
||||
renderingData,
|
||||
passEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using XCEngine;
|
||||
using XCEngine.Rendering;
|
||||
|
||||
namespace XCEngine.Rendering.Universal
|
||||
{
|
||||
|
||||
@@ -6,24 +6,31 @@ namespace XCEngine.Rendering.Universal
|
||||
internal sealed class ColorScalePostProcessPass
|
||||
: ScriptableRenderPass
|
||||
{
|
||||
private readonly ColorScalePostProcessRendererFeature m_feature;
|
||||
private Vector4 m_colorScale = new Vector4(
|
||||
1.0f,
|
||||
1.0f,
|
||||
1.0f,
|
||||
1.0f);
|
||||
|
||||
public ColorScalePostProcessPass(
|
||||
ColorScalePostProcessRendererFeature feature)
|
||||
public ColorScalePostProcessPass()
|
||||
{
|
||||
m_feature = feature;
|
||||
renderPassEvent =
|
||||
RenderPassEvent.BeforeRenderingPostProcessing;
|
||||
}
|
||||
|
||||
public void Configure(
|
||||
Vector4 colorScale)
|
||||
{
|
||||
m_colorScale = colorScale;
|
||||
}
|
||||
|
||||
protected override bool RecordRenderGraph(
|
||||
ScriptableRenderContext context,
|
||||
RenderingData renderingData)
|
||||
{
|
||||
if (context == null ||
|
||||
renderingData == null ||
|
||||
!renderingData.isPostProcessStage ||
|
||||
m_feature == null)
|
||||
!renderingData.isPostProcessStage)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -32,7 +39,7 @@ namespace XCEngine.Rendering.Universal
|
||||
context,
|
||||
context.sourceColorTexture,
|
||||
context.primaryColorTarget,
|
||||
m_feature.colorScale,
|
||||
m_colorScale,
|
||||
"Universal.ColorScalePostProcess");
|
||||
}
|
||||
}
|
||||
@@ -40,8 +47,9 @@ namespace XCEngine.Rendering.Universal
|
||||
public sealed class ColorScalePostProcessRendererFeature
|
||||
: ScriptableRendererFeature
|
||||
{
|
||||
private ColorScalePostProcessPass m_pass;
|
||||
|
||||
private readonly UniversalColorScalePostProcessController
|
||||
m_controller =
|
||||
new UniversalColorScalePostProcessController();
|
||||
public Vector4 colorScale = new Vector4(
|
||||
1.0f,
|
||||
1.0f,
|
||||
@@ -52,17 +60,22 @@ namespace XCEngine.Rendering.Universal
|
||||
{
|
||||
int hash =
|
||||
base.ComputeRuntimeStateHash();
|
||||
hash =
|
||||
RuntimeStateHashUtility.Combine(
|
||||
hash,
|
||||
colorScale);
|
||||
return hash;
|
||||
return m_controller.AppendRuntimeStateHash(
|
||||
hash,
|
||||
BuildSettings());
|
||||
}
|
||||
|
||||
public override void Create()
|
||||
{
|
||||
m_pass =
|
||||
new ColorScalePostProcessPass(this);
|
||||
m_controller.Create(
|
||||
BuildSettings());
|
||||
}
|
||||
|
||||
public override void ConfigureCameraFramePlan(
|
||||
ScriptableRenderPipelinePlanningContext context)
|
||||
{
|
||||
m_controller.ConfigureCameraFramePlan(
|
||||
context);
|
||||
}
|
||||
|
||||
public override void AddRenderPasses(
|
||||
@@ -70,14 +83,25 @@ namespace XCEngine.Rendering.Universal
|
||||
RenderingData renderingData)
|
||||
{
|
||||
if (renderer == null ||
|
||||
renderingData == null)
|
||||
renderingData == null ||
|
||||
!renderingData.isPostProcessStage)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CreateInstance();
|
||||
m_controller.EnqueuePass(
|
||||
renderer,
|
||||
renderingData,
|
||||
BuildSettings());
|
||||
}
|
||||
|
||||
renderer.EnqueuePass(m_pass);
|
||||
private ColorScalePostProcessSettings BuildSettings()
|
||||
{
|
||||
return new ColorScalePostProcessSettings
|
||||
{
|
||||
colorScale = colorScale
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
using XCEngine;
|
||||
|
||||
namespace XCEngine.Rendering.Universal
|
||||
{
|
||||
internal sealed class ColorScalePostProcessSettings
|
||||
{
|
||||
public Vector4 colorScale = new Vector4(
|
||||
1.0f,
|
||||
1.0f,
|
||||
1.0f,
|
||||
1.0f);
|
||||
|
||||
public int AppendRuntimeStateHash(
|
||||
int hash)
|
||||
{
|
||||
return RuntimeStateHashUtility.Combine(
|
||||
hash,
|
||||
colorScale);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,14 +6,14 @@ namespace XCEngine.Rendering.Universal
|
||||
internal sealed class NativeSceneFeaturePass
|
||||
: ScriptableRenderPass
|
||||
{
|
||||
private readonly string m_featurePassName;
|
||||
private readonly NativeSceneFeaturePassId m_featurePassId;
|
||||
|
||||
public NativeSceneFeaturePass(
|
||||
string featurePassName,
|
||||
NativeSceneFeaturePassId featurePassId,
|
||||
RenderPassEvent passEvent)
|
||||
{
|
||||
m_featurePassName =
|
||||
featurePassName ?? string.Empty;
|
||||
m_featurePassId =
|
||||
featurePassId;
|
||||
renderPassEvent = passEvent;
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace XCEngine.Rendering.Universal
|
||||
renderingData != null &&
|
||||
renderingData.isMainSceneStage &&
|
||||
context.RecordNativeSceneFeaturePass(
|
||||
m_featurePassName);
|
||||
m_featurePassId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
using XCEngine;
|
||||
using XCEngine.Rendering;
|
||||
|
||||
namespace XCEngine.Rendering.Universal
|
||||
{
|
||||
internal sealed class RenderObjectsFeatureSettings
|
||||
{
|
||||
public RenderPassEvent passEvent =
|
||||
RenderPassEvent.AfterRenderingOpaques;
|
||||
public SceneRenderPhase scenePhase =
|
||||
SceneRenderPhase.Opaque;
|
||||
public RendererListDesc rendererListDesc =
|
||||
RendererListDesc.CreateDefault(
|
||||
RendererListType.Opaque);
|
||||
public DrawingSettings drawingSettings =
|
||||
DrawingSettings.CreateDefault();
|
||||
|
||||
public int AppendRuntimeStateHash(
|
||||
int hash)
|
||||
{
|
||||
hash = RuntimeStateHashUtility.Combine(
|
||||
hash,
|
||||
(int)passEvent);
|
||||
hash = RuntimeStateHashUtility.Combine(
|
||||
hash,
|
||||
(int)scenePhase);
|
||||
hash = RuntimeStateHashUtility.Combine(
|
||||
hash,
|
||||
rendererListDesc);
|
||||
hash = RuntimeStateHashUtility.Combine(
|
||||
hash,
|
||||
drawingSettings);
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,9 @@ namespace XCEngine.Rendering.Universal
|
||||
public sealed class RenderObjectsRendererFeature
|
||||
: ScriptableRendererFeature
|
||||
{
|
||||
private DrawObjectsPass m_pass;
|
||||
private readonly UniversalRenderObjectsFeatureController
|
||||
m_controller =
|
||||
new UniversalRenderObjectsFeatureController();
|
||||
|
||||
public RenderPassEvent passEvent =
|
||||
RenderPassEvent.AfterRenderingOpaques;
|
||||
@@ -32,91 +34,15 @@ namespace XCEngine.Rendering.Universal
|
||||
{
|
||||
int hash =
|
||||
base.ComputeRuntimeStateHash();
|
||||
hash =
|
||||
RuntimeStateHashUtility.Combine(
|
||||
hash,
|
||||
(int)passEvent);
|
||||
hash =
|
||||
RuntimeStateHashUtility.Combine(
|
||||
hash,
|
||||
(int)scenePhase);
|
||||
hash =
|
||||
RuntimeStateHashUtility.Combine(
|
||||
hash,
|
||||
(int)rendererListType);
|
||||
hash =
|
||||
RuntimeStateHashUtility.Combine(
|
||||
hash,
|
||||
overrideRenderQueueRange);
|
||||
hash =
|
||||
RuntimeStateHashUtility.Combine(
|
||||
hash,
|
||||
renderQueueRange);
|
||||
hash =
|
||||
RuntimeStateHashUtility.Combine(
|
||||
hash,
|
||||
overrideRenderLayerMask);
|
||||
hash =
|
||||
RuntimeStateHashUtility.Combine(
|
||||
hash,
|
||||
renderLayerMask);
|
||||
hash =
|
||||
RuntimeStateHashUtility.Combine(
|
||||
hash,
|
||||
overrideMaterialPath);
|
||||
hash =
|
||||
RuntimeStateHashUtility.Combine(
|
||||
hash,
|
||||
shaderPassName);
|
||||
hash =
|
||||
RuntimeStateHashUtility.Combine(
|
||||
hash,
|
||||
overrideRenderStateBlock);
|
||||
hash =
|
||||
RuntimeStateHashUtility.Combine(
|
||||
hash,
|
||||
renderStateBlock);
|
||||
hash =
|
||||
RuntimeStateHashUtility.Combine(
|
||||
hash,
|
||||
overrideFilteringSettings);
|
||||
hash =
|
||||
RuntimeStateHashUtility.Combine(
|
||||
hash,
|
||||
filteringSettings);
|
||||
hash =
|
||||
RuntimeStateHashUtility.Combine(
|
||||
hash,
|
||||
overrideSortingSettings);
|
||||
hash =
|
||||
RuntimeStateHashUtility.Combine(
|
||||
hash,
|
||||
sortingSettings);
|
||||
return hash;
|
||||
return m_controller.AppendRuntimeStateHash(
|
||||
hash,
|
||||
BuildSettings());
|
||||
}
|
||||
|
||||
public override void Create()
|
||||
{
|
||||
RendererListDesc rendererListDesc =
|
||||
BuildRendererListDesc();
|
||||
DrawingSettings drawingSettings =
|
||||
BuildDrawingSettings();
|
||||
if (m_pass == null)
|
||||
{
|
||||
m_pass =
|
||||
new DrawObjectsPass(
|
||||
passEvent,
|
||||
scenePhase,
|
||||
rendererListDesc,
|
||||
drawingSettings);
|
||||
return;
|
||||
}
|
||||
|
||||
m_pass.Configure(
|
||||
passEvent,
|
||||
scenePhase,
|
||||
rendererListDesc,
|
||||
drawingSettings);
|
||||
m_controller.Create(
|
||||
BuildSettings());
|
||||
}
|
||||
|
||||
public override void AddRenderPasses(
|
||||
@@ -130,13 +56,21 @@ namespace XCEngine.Rendering.Universal
|
||||
}
|
||||
|
||||
CreateInstance();
|
||||
m_controller.EnqueuePass(
|
||||
renderer,
|
||||
renderingData,
|
||||
BuildSettings());
|
||||
}
|
||||
|
||||
m_pass.Configure(
|
||||
passEvent,
|
||||
scenePhase,
|
||||
BuildRendererListDesc(),
|
||||
BuildDrawingSettings());
|
||||
renderer.EnqueuePass(m_pass);
|
||||
private RenderObjectsFeatureSettings BuildSettings()
|
||||
{
|
||||
return new RenderObjectsFeatureSettings
|
||||
{
|
||||
passEvent = passEvent,
|
||||
scenePhase = scenePhase,
|
||||
rendererListDesc = BuildRendererListDesc(),
|
||||
drawingSettings = BuildDrawingSettings()
|
||||
};
|
||||
}
|
||||
|
||||
private RendererListDesc BuildRendererListDesc()
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using XCEngine;
|
||||
using XCEngine.Rendering;
|
||||
|
||||
@@ -11,11 +10,15 @@ namespace XCEngine.Rendering.Universal
|
||||
public ScriptableRendererData[] rendererDataList =
|
||||
Array.Empty<ScriptableRendererData>();
|
||||
public int defaultRendererIndex = 0;
|
||||
private readonly ScriptableRendererDataCollection
|
||||
m_rendererDataCollection;
|
||||
private int m_rendererDataRuntimeStateHash;
|
||||
private bool m_rendererDataRuntimeStateHashResolved;
|
||||
|
||||
protected RendererBackedRenderPipelineAsset()
|
||||
{
|
||||
m_rendererDataCollection =
|
||||
new ScriptableRendererDataCollection();
|
||||
}
|
||||
|
||||
protected override ScriptableRenderPipeline CreatePipeline()
|
||||
@@ -96,30 +99,21 @@ namespace XCEngine.Rendering.Universal
|
||||
|
||||
protected override void ReleaseRuntimeResources()
|
||||
{
|
||||
ReleaseRendererDataRuntimeResources();
|
||||
m_rendererDataCollection.ReleaseRuntimeResources(
|
||||
ref rendererDataList,
|
||||
ref defaultRendererIndex,
|
||||
CreateDefaultRendererData);
|
||||
}
|
||||
|
||||
protected override void SynchronizeRuntimeResourceVersion()
|
||||
{
|
||||
int runtimeStateHash =
|
||||
ComputeRendererDataRuntimeStateHash();
|
||||
if (!m_rendererDataRuntimeStateHashResolved)
|
||||
{
|
||||
m_rendererDataRuntimeStateHash =
|
||||
runtimeStateHash;
|
||||
m_rendererDataRuntimeStateHashResolved = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (runtimeStateHash ==
|
||||
m_rendererDataRuntimeStateHash)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_rendererDataRuntimeStateHash =
|
||||
runtimeStateHash;
|
||||
SetDirty();
|
||||
m_rendererDataCollection.Synchronize(
|
||||
ref rendererDataList,
|
||||
ref defaultRendererIndex,
|
||||
ref m_rendererDataRuntimeStateHash,
|
||||
ref m_rendererDataRuntimeStateHashResolved,
|
||||
CreateDefaultRendererData,
|
||||
SetDirty);
|
||||
}
|
||||
|
||||
protected virtual ScriptableRenderPipeline
|
||||
@@ -150,15 +144,12 @@ namespace XCEngine.Rendering.Universal
|
||||
return true;
|
||||
}
|
||||
|
||||
private protected override bool UsesNativeCameraFramePlanBaselineContextual(
|
||||
int rendererIndex)
|
||||
{
|
||||
return UsesExplicitFullscreenStagePlanning();
|
||||
}
|
||||
|
||||
internal ScriptableRendererData GetDefaultRendererData()
|
||||
{
|
||||
return ResolveSelectedRendererData();
|
||||
return m_rendererDataCollection.GetDefaultRendererData(
|
||||
ref rendererDataList,
|
||||
ref defaultRendererIndex,
|
||||
CreateDefaultRendererData);
|
||||
}
|
||||
|
||||
internal ScriptableRenderer GetDefaultRenderer()
|
||||
@@ -168,8 +159,7 @@ namespace XCEngine.Rendering.Universal
|
||||
|
||||
internal ScriptableRendererData ResolveSelectedRendererData()
|
||||
{
|
||||
return ResolveRendererDataByResolvedIndex(
|
||||
ResolveSelectedRendererIndex());
|
||||
return GetDefaultRendererData();
|
||||
}
|
||||
|
||||
internal ScriptableRenderer ResolveSelectedRenderer()
|
||||
@@ -184,9 +174,11 @@ namespace XCEngine.Rendering.Universal
|
||||
internal ScriptableRendererData GetRendererData(
|
||||
int rendererIndex)
|
||||
{
|
||||
return ResolveRendererDataByResolvedIndex(
|
||||
ResolveRendererIndexWithFallback(
|
||||
rendererIndex));
|
||||
return m_rendererDataCollection.GetRendererData(
|
||||
ref rendererDataList,
|
||||
ref defaultRendererIndex,
|
||||
rendererIndex,
|
||||
CreateDefaultRendererData);
|
||||
}
|
||||
|
||||
internal ScriptableRenderer ResolveRenderer(
|
||||
@@ -199,113 +191,13 @@ namespace XCEngine.Rendering.Universal
|
||||
: null;
|
||||
}
|
||||
|
||||
protected internal void ReleaseRendererDataRuntimeResources()
|
||||
{
|
||||
EnsureRendererDataList();
|
||||
|
||||
for (int i = 0; i < rendererDataList.Length; ++i)
|
||||
{
|
||||
ScriptableRendererData rendererData =
|
||||
rendererDataList[i];
|
||||
if (rendererData == null ||
|
||||
WasRendererDataReleasedEarlier(i))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
rendererData.ReleaseRuntimeResourcesInstance();
|
||||
}
|
||||
}
|
||||
|
||||
private void EnsureRendererDataList()
|
||||
{
|
||||
if (rendererDataList != null &&
|
||||
rendererDataList.Length > 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ScriptableRendererData defaultRendererData =
|
||||
CreateDefaultRendererData();
|
||||
rendererDataList =
|
||||
defaultRendererData != null
|
||||
? new ScriptableRendererData[]
|
||||
{
|
||||
defaultRendererData
|
||||
}
|
||||
: Array.Empty<ScriptableRendererData>();
|
||||
defaultRendererIndex = 0;
|
||||
}
|
||||
|
||||
private bool WasRendererDataReleasedEarlier(
|
||||
int rendererDataIndex)
|
||||
{
|
||||
ScriptableRendererData rendererData =
|
||||
rendererDataList[rendererDataIndex];
|
||||
for (int i = 0; i < rendererDataIndex; ++i)
|
||||
{
|
||||
if (object.ReferenceEquals(
|
||||
rendererDataList[i],
|
||||
rendererData))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private int ComputeRendererDataRuntimeStateHash()
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
int hash = 17;
|
||||
hash =
|
||||
(hash * 31) +
|
||||
ResolveSelectedRendererIndex();
|
||||
if (rendererDataList == null)
|
||||
{
|
||||
return hash;
|
||||
}
|
||||
|
||||
hash = (hash * 31) + rendererDataList.Length;
|
||||
for (int i = 0; i < rendererDataList.Length; ++i)
|
||||
{
|
||||
ScriptableRendererData rendererData =
|
||||
rendererDataList[i];
|
||||
if (rendererData != null)
|
||||
{
|
||||
hash =
|
||||
(hash * 31) +
|
||||
RuntimeHelpers.GetHashCode(
|
||||
rendererData);
|
||||
hash =
|
||||
(hash * 31) +
|
||||
rendererData
|
||||
.GetRuntimeStateVersionInstance();
|
||||
}
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
|
||||
private ScriptableRendererData ResolveRendererDataByResolvedIndex(
|
||||
int resolvedRendererIndex)
|
||||
{
|
||||
EnsureRendererDataList();
|
||||
if (resolvedRendererIndex < 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return rendererDataList[resolvedRendererIndex];
|
||||
}
|
||||
|
||||
private int ResolveSelectedRendererIndex()
|
||||
{
|
||||
return ResolveRendererIndexWithFallback(
|
||||
defaultRendererIndex);
|
||||
return m_rendererDataCollection
|
||||
.ResolveDefaultRendererIndex(
|
||||
ref rendererDataList,
|
||||
ref defaultRendererIndex,
|
||||
CreateDefaultRendererData);
|
||||
}
|
||||
|
||||
private ScriptableRendererData ResolveRendererData(
|
||||
@@ -354,76 +246,12 @@ namespace XCEngine.Rendering.Universal
|
||||
}
|
||||
|
||||
context.rendererIndex =
|
||||
ResolveRendererIndexWithFallback(
|
||||
rendererIndex);
|
||||
}
|
||||
|
||||
private int ResolveRendererIndexWithFallback(
|
||||
int rendererIndex)
|
||||
{
|
||||
EnsureRendererDataList();
|
||||
if (rendererDataList.Length == 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (rendererIndex < 0 ||
|
||||
rendererIndex >= rendererDataList.Length)
|
||||
{
|
||||
return ResolveDefaultRendererIndex();
|
||||
}
|
||||
|
||||
if (rendererDataList[rendererIndex] == null)
|
||||
{
|
||||
return ResolveDefaultRendererIndex();
|
||||
}
|
||||
|
||||
return rendererIndex;
|
||||
}
|
||||
|
||||
private int ResolveDefaultRendererIndex()
|
||||
{
|
||||
EnsureRendererDataList();
|
||||
if (rendererDataList.Length == 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (defaultRendererIndex < 0 ||
|
||||
defaultRendererIndex >= rendererDataList.Length)
|
||||
{
|
||||
defaultRendererIndex = 0;
|
||||
}
|
||||
|
||||
if (rendererDataList[defaultRendererIndex] != null)
|
||||
{
|
||||
return defaultRendererIndex;
|
||||
}
|
||||
|
||||
int firstValidRendererIndex =
|
||||
FindFirstValidRendererIndex();
|
||||
if (firstValidRendererIndex >= 0)
|
||||
{
|
||||
defaultRendererIndex = firstValidRendererIndex;
|
||||
return defaultRendererIndex;
|
||||
}
|
||||
|
||||
rendererDataList[defaultRendererIndex] =
|
||||
CreateDefaultRendererData();
|
||||
return defaultRendererIndex;
|
||||
}
|
||||
|
||||
private int FindFirstValidRendererIndex()
|
||||
{
|
||||
for (int i = 0; i < rendererDataList.Length; ++i)
|
||||
{
|
||||
if (rendererDataList[i] != null)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
m_rendererDataCollection
|
||||
.ResolveRendererIndexWithFallback(
|
||||
ref rendererDataList,
|
||||
ref defaultRendererIndex,
|
||||
rendererIndex,
|
||||
CreateDefaultRendererData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
using XCEngine.Rendering;
|
||||
|
||||
namespace XCEngine.Rendering.Universal
|
||||
{
|
||||
internal enum RendererBlock
|
||||
{
|
||||
ShadowCaster = 0,
|
||||
DepthPrepass = 1,
|
||||
MainOpaque = 2,
|
||||
MainSkybox = 3,
|
||||
MainTransparent = 4,
|
||||
PostProcess = 5,
|
||||
FinalOutput = 6,
|
||||
Count = 7
|
||||
}
|
||||
|
||||
internal static class RendererBlockUtility
|
||||
{
|
||||
public static CameraFrameStage GetStage(
|
||||
RendererBlock block)
|
||||
{
|
||||
switch (block)
|
||||
{
|
||||
case RendererBlock.ShadowCaster:
|
||||
return CameraFrameStage.ShadowCaster;
|
||||
case RendererBlock.DepthPrepass:
|
||||
return CameraFrameStage.DepthOnly;
|
||||
case RendererBlock.MainOpaque:
|
||||
case RendererBlock.MainSkybox:
|
||||
case RendererBlock.MainTransparent:
|
||||
return CameraFrameStage.MainScene;
|
||||
case RendererBlock.PostProcess:
|
||||
return CameraFrameStage.PostProcess;
|
||||
case RendererBlock.FinalOutput:
|
||||
return CameraFrameStage.FinalOutput;
|
||||
default:
|
||||
return CameraFrameStage.MainScene;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace XCEngine.Rendering.Universal
|
||||
{
|
||||
internal sealed class RendererBlocks
|
||||
{
|
||||
private struct BlockRange
|
||||
{
|
||||
public int firstPassIndex;
|
||||
public int lastPassIndex;
|
||||
}
|
||||
|
||||
private readonly BlockRange[] m_ranges =
|
||||
new BlockRange[(int)RendererBlock.Count];
|
||||
|
||||
public RendererBlocks()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
for (int i = 0; i < m_ranges.Length; ++i)
|
||||
{
|
||||
m_ranges[i].firstPassIndex = -1;
|
||||
m_ranges[i].lastPassIndex = -1;
|
||||
}
|
||||
}
|
||||
|
||||
public void Build(
|
||||
IList<ScriptableRenderPass> activePassQueue)
|
||||
{
|
||||
Clear();
|
||||
|
||||
if (activePassQueue == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < activePassQueue.Count; ++i)
|
||||
{
|
||||
ScriptableRenderPass renderPass =
|
||||
activePassQueue[i];
|
||||
if (renderPass == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
RendererBlock block;
|
||||
if (!ScriptableRenderPass.TryResolveRendererBlock(
|
||||
renderPass.renderPassEvent,
|
||||
out block))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
int blockIndex = (int)block;
|
||||
BlockRange range = m_ranges[blockIndex];
|
||||
if (range.firstPassIndex < 0)
|
||||
{
|
||||
range.firstPassIndex = i;
|
||||
}
|
||||
|
||||
range.lastPassIndex = i;
|
||||
m_ranges[blockIndex] = range;
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasPasses(
|
||||
RendererBlock block)
|
||||
{
|
||||
BlockRange range = m_ranges[(int)block];
|
||||
return range.firstPassIndex >= 0 &&
|
||||
range.lastPassIndex >= range.firstPassIndex;
|
||||
}
|
||||
|
||||
public bool TryGetPassRange(
|
||||
RendererBlock block,
|
||||
out int firstPassIndex,
|
||||
out int lastPassIndex)
|
||||
{
|
||||
BlockRange range = m_ranges[(int)block];
|
||||
firstPassIndex = range.firstPassIndex;
|
||||
lastPassIndex = range.lastPassIndex;
|
||||
return range.firstPassIndex >= 0 &&
|
||||
range.lastPassIndex >= range.firstPassIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -75,6 +75,44 @@ namespace XCEngine.Rendering.Universal
|
||||
}
|
||||
}
|
||||
|
||||
public RenderClearFlags clearFlags
|
||||
{
|
||||
get =>
|
||||
m_requestContext != null
|
||||
? m_requestContext.clearFlags
|
||||
: RenderClearFlags.All;
|
||||
set
|
||||
{
|
||||
if (m_requestContext != null)
|
||||
{
|
||||
m_requestContext.clearFlags = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void SetResolvedFinalColorPolicy(
|
||||
FinalColorSettings settings,
|
||||
bool hasPipelineDefaults,
|
||||
bool hasCameraOverrides)
|
||||
{
|
||||
if (m_requestContext != null)
|
||||
{
|
||||
m_requestContext
|
||||
.SetResolvedFinalColorPolicy(
|
||||
settings,
|
||||
hasPipelineDefaults,
|
||||
hasCameraOverrides);
|
||||
}
|
||||
}
|
||||
|
||||
public void ClearFinalColorPolicy()
|
||||
{
|
||||
if (m_requestContext != null)
|
||||
{
|
||||
m_requestContext.ClearFinalColorPolicy();
|
||||
}
|
||||
}
|
||||
|
||||
internal CameraRenderRequestContext requestContext =>
|
||||
m_requestContext;
|
||||
}
|
||||
|
||||
@@ -23,11 +23,21 @@ namespace XCEngine.Rendering.Universal
|
||||
public virtual bool SupportsStage(
|
||||
CameraFrameStage stage)
|
||||
{
|
||||
CameraFrameStage resolvedStage;
|
||||
return TryResolveStage(
|
||||
RendererBlock block;
|
||||
return TryResolveRendererBlock(
|
||||
renderPassEvent,
|
||||
out resolvedStage) &&
|
||||
resolvedStage == stage;
|
||||
out block) &&
|
||||
RendererBlockUtility.GetStage(block) == stage;
|
||||
}
|
||||
|
||||
internal bool SupportsRendererBlock(
|
||||
RendererBlock block)
|
||||
{
|
||||
RendererBlock resolvedBlock;
|
||||
return TryResolveRendererBlock(
|
||||
renderPassEvent,
|
||||
out resolvedBlock) &&
|
||||
resolvedBlock == block;
|
||||
}
|
||||
|
||||
internal bool Record(
|
||||
@@ -209,38 +219,60 @@ namespace XCEngine.Rendering.Universal
|
||||
internal static bool TryResolveStage(
|
||||
RenderPassEvent passEvent,
|
||||
out CameraFrameStage stage)
|
||||
{
|
||||
RendererBlock block;
|
||||
if (TryResolveRendererBlock(
|
||||
passEvent,
|
||||
out block))
|
||||
{
|
||||
stage =
|
||||
RendererBlockUtility.GetStage(block);
|
||||
return true;
|
||||
}
|
||||
|
||||
stage = CameraFrameStage.MainScene;
|
||||
return false;
|
||||
}
|
||||
|
||||
internal static bool TryResolveRendererBlock(
|
||||
RenderPassEvent passEvent,
|
||||
out RendererBlock block)
|
||||
{
|
||||
switch (passEvent)
|
||||
{
|
||||
case RenderPassEvent.BeforeRenderingShadows:
|
||||
case RenderPassEvent.AfterRenderingShadows:
|
||||
stage = CameraFrameStage.ShadowCaster;
|
||||
block = RendererBlock.ShadowCaster;
|
||||
return true;
|
||||
case RenderPassEvent.BeforeRenderingPrePasses:
|
||||
case RenderPassEvent.AfterRenderingPrePasses:
|
||||
stage = CameraFrameStage.DepthOnly;
|
||||
block = RendererBlock.DepthPrepass;
|
||||
return true;
|
||||
case RenderPassEvent.BeforeRenderingOpaques:
|
||||
case RenderPassEvent.RenderOpaques:
|
||||
case RenderPassEvent.AfterRenderingOpaques:
|
||||
block = RendererBlock.MainOpaque;
|
||||
return true;
|
||||
case RenderPassEvent.BeforeRenderingSkybox:
|
||||
case RenderPassEvent.RenderSkybox:
|
||||
case RenderPassEvent.AfterRenderingSkybox:
|
||||
block = RendererBlock.MainSkybox;
|
||||
return true;
|
||||
case RenderPassEvent.BeforeRenderingTransparents:
|
||||
case RenderPassEvent.RenderTransparents:
|
||||
case RenderPassEvent.AfterRenderingTransparents:
|
||||
stage = CameraFrameStage.MainScene;
|
||||
block = RendererBlock.MainTransparent;
|
||||
return true;
|
||||
case RenderPassEvent.BeforeRenderingPostProcessing:
|
||||
case RenderPassEvent.AfterRenderingPostProcessing:
|
||||
stage = CameraFrameStage.PostProcess;
|
||||
block = RendererBlock.PostProcess;
|
||||
return true;
|
||||
case RenderPassEvent.BeforeRenderingFinalOutput:
|
||||
case RenderPassEvent.AfterRenderingFinalOutput:
|
||||
stage = CameraFrameStage.FinalOutput;
|
||||
block = RendererBlock.FinalOutput;
|
||||
return true;
|
||||
default:
|
||||
stage = CameraFrameStage.MainScene;
|
||||
block = RendererBlock.MainOpaque;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,11 @@ namespace XCEngine.Rendering.Universal
|
||||
new List<ScriptableRendererFeature>();
|
||||
private readonly List<ScriptableRenderPass> m_activePassQueue =
|
||||
new List<ScriptableRenderPass>();
|
||||
private readonly RendererBlocks m_rendererBlocks =
|
||||
new RendererBlocks();
|
||||
private bool m_isBuildingPassQueue;
|
||||
private CameraFrameStage m_passQueueStage =
|
||||
CameraFrameStage.MainScene;
|
||||
private bool m_disposed;
|
||||
|
||||
protected ScriptableRenderer()
|
||||
@@ -36,6 +41,7 @@ namespace XCEngine.Rendering.Universal
|
||||
|
||||
m_features.Clear();
|
||||
m_activePassQueue.Clear();
|
||||
m_rendererBlocks.Clear();
|
||||
m_disposed = true;
|
||||
}
|
||||
|
||||
@@ -47,6 +53,19 @@ namespace XCEngine.Rendering.Universal
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_isBuildingPassQueue &&
|
||||
!renderPass.SupportsStage(m_passQueueStage))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
InsertActivePass(
|
||||
renderPass);
|
||||
}
|
||||
|
||||
private void InsertActivePass(
|
||||
ScriptableRenderPass renderPass)
|
||||
{
|
||||
int insertIndex = m_activePassQueue.Count;
|
||||
while (insertIndex > 0 &&
|
||||
m_activePassQueue[insertIndex - 1].renderPassEvent >
|
||||
@@ -130,17 +149,7 @@ namespace XCEngine.Rendering.Universal
|
||||
RenderingData renderingData =
|
||||
context.renderingData;
|
||||
BuildPassQueue(renderingData);
|
||||
for (int i = 0; i < m_activePassQueue.Count; ++i)
|
||||
{
|
||||
ScriptableRenderPass renderPass = m_activePassQueue[i];
|
||||
if (renderPass != null &&
|
||||
renderPass.SupportsStage(context.stage))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return SupportsRendererStage(context);
|
||||
}
|
||||
|
||||
protected virtual bool RecordRenderer(
|
||||
@@ -155,28 +164,7 @@ namespace XCEngine.Rendering.Universal
|
||||
RenderingData renderingData =
|
||||
context.renderingData;
|
||||
BuildPassQueue(renderingData);
|
||||
|
||||
bool recordedAnyPass = false;
|
||||
for (int i = 0; i < m_activePassQueue.Count; ++i)
|
||||
{
|
||||
ScriptableRenderPass renderPass = m_activePassQueue[i];
|
||||
if (renderPass == null ||
|
||||
!renderPass.SupportsStage(renderingData.stage))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!renderPass.Record(
|
||||
context.renderContext,
|
||||
renderingData))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
recordedAnyPass = true;
|
||||
}
|
||||
|
||||
return recordedAnyPass;
|
||||
return RecordRendererStage(context);
|
||||
}
|
||||
|
||||
protected internal virtual bool SupportsStageRenderGraph(
|
||||
@@ -202,13 +190,6 @@ namespace XCEngine.Rendering.Universal
|
||||
protected virtual void FinalizeCameraFramePlan(
|
||||
ScriptableRenderPipelinePlanningContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ApplyInferredFullscreenStageRequests(
|
||||
context);
|
||||
}
|
||||
|
||||
protected virtual void ConfigureRenderSceneSetup(
|
||||
@@ -221,155 +202,187 @@ namespace XCEngine.Rendering.Universal
|
||||
{
|
||||
}
|
||||
|
||||
private void BuildPassQueue(
|
||||
RenderingData renderingData)
|
||||
private bool HasRendererBlock(
|
||||
RendererBlock block)
|
||||
{
|
||||
m_activePassQueue.Clear();
|
||||
return m_rendererBlocks.HasPasses(block);
|
||||
}
|
||||
|
||||
for (int i = 0; i < m_features.Count; ++i)
|
||||
protected virtual bool SupportsRendererStage(
|
||||
RendererRecordingContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
ScriptableRendererFeature feature = m_features[i];
|
||||
if (feature == null || !feature.isActive)
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (context.stage)
|
||||
{
|
||||
case CameraFrameStage.ShadowCaster:
|
||||
return HasRendererBlock(
|
||||
RendererBlock.ShadowCaster);
|
||||
case CameraFrameStage.DepthOnly:
|
||||
return HasRendererBlock(
|
||||
RendererBlock.DepthPrepass);
|
||||
case CameraFrameStage.MainScene:
|
||||
return HasRendererBlock(
|
||||
RendererBlock.MainOpaque) ||
|
||||
HasRendererBlock(
|
||||
RendererBlock.MainSkybox) ||
|
||||
HasRendererBlock(
|
||||
RendererBlock.MainTransparent);
|
||||
case CameraFrameStage.PostProcess:
|
||||
return HasRendererBlock(
|
||||
RendererBlock.PostProcess);
|
||||
case CameraFrameStage.FinalOutput:
|
||||
return HasRendererBlock(
|
||||
RendererBlock.FinalOutput);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual bool RecordRendererStage(
|
||||
RendererRecordingContext context)
|
||||
{
|
||||
if (context == null ||
|
||||
context.renderContext == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool recordedAnyPass = false;
|
||||
switch (context.stage)
|
||||
{
|
||||
case CameraFrameStage.ShadowCaster:
|
||||
return RecordRendererBlock(
|
||||
RendererBlock.ShadowCaster,
|
||||
context,
|
||||
ref recordedAnyPass) &&
|
||||
recordedAnyPass;
|
||||
case CameraFrameStage.DepthOnly:
|
||||
return RecordRendererBlock(
|
||||
RendererBlock.DepthPrepass,
|
||||
context,
|
||||
ref recordedAnyPass) &&
|
||||
recordedAnyPass;
|
||||
case CameraFrameStage.MainScene:
|
||||
return RecordRendererBlock(
|
||||
RendererBlock.MainOpaque,
|
||||
context,
|
||||
ref recordedAnyPass) &&
|
||||
RecordRendererBlock(
|
||||
RendererBlock.MainSkybox,
|
||||
context,
|
||||
ref recordedAnyPass) &&
|
||||
RecordRendererBlock(
|
||||
RendererBlock.MainTransparent,
|
||||
context,
|
||||
ref recordedAnyPass) &&
|
||||
recordedAnyPass;
|
||||
case CameraFrameStage.PostProcess:
|
||||
return RecordRendererBlock(
|
||||
RendererBlock.PostProcess,
|
||||
context,
|
||||
ref recordedAnyPass) &&
|
||||
recordedAnyPass;
|
||||
case CameraFrameStage.FinalOutput:
|
||||
return RecordRendererBlock(
|
||||
RendererBlock.FinalOutput,
|
||||
context,
|
||||
ref recordedAnyPass) &&
|
||||
recordedAnyPass;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private bool RecordRendererBlock(
|
||||
RendererBlock block,
|
||||
RendererRecordingContext context,
|
||||
ref bool recordedAnyPass)
|
||||
{
|
||||
if (context == null ||
|
||||
context.renderContext == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int firstPassIndex;
|
||||
int lastPassIndex;
|
||||
if (!m_rendererBlocks.TryGetPassRange(
|
||||
block,
|
||||
out firstPassIndex,
|
||||
out lastPassIndex))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
for (int i = firstPassIndex;
|
||||
i <= lastPassIndex;
|
||||
++i)
|
||||
{
|
||||
ScriptableRenderPass renderPass =
|
||||
m_activePassQueue[i];
|
||||
if (renderPass == null ||
|
||||
!renderPass.SupportsRendererBlock(block))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
feature.AddRenderPasses(
|
||||
this,
|
||||
renderingData);
|
||||
if (!renderPass.Record(
|
||||
context.renderContext,
|
||||
context.renderingData))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
recordedAnyPass = true;
|
||||
}
|
||||
|
||||
AddRenderPasses(renderingData);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void BuildPassQueue(
|
||||
RenderingData renderingData)
|
||||
{
|
||||
m_activePassQueue.Clear();
|
||||
m_rendererBlocks.Clear();
|
||||
m_isBuildingPassQueue = true;
|
||||
m_passQueueStage =
|
||||
renderingData != null
|
||||
? renderingData.stage
|
||||
: CameraFrameStage.MainScene;
|
||||
|
||||
try
|
||||
{
|
||||
for (int i = 0; i < m_features.Count; ++i)
|
||||
{
|
||||
ScriptableRendererFeature feature = m_features[i];
|
||||
if (feature == null || !feature.isActive)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
feature.AddRenderPasses(
|
||||
this,
|
||||
renderingData);
|
||||
}
|
||||
|
||||
AddRenderPasses(renderingData);
|
||||
m_rendererBlocks.Build(m_activePassQueue);
|
||||
}
|
||||
finally
|
||||
{
|
||||
m_isBuildingPassQueue = false;
|
||||
m_passQueueStage =
|
||||
CameraFrameStage.MainScene;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void ReleaseRuntimeResources()
|
||||
{
|
||||
}
|
||||
|
||||
protected virtual RenderingData CreatePlanningRenderingData(
|
||||
ScriptableRenderPipelinePlanningContext context)
|
||||
{
|
||||
return context != null
|
||||
? new RenderingData(
|
||||
CameraFrameStage.MainScene,
|
||||
context.rendererIndex)
|
||||
: null;
|
||||
}
|
||||
|
||||
private void ApplyInferredFullscreenStageRequests(
|
||||
ScriptableRenderPipelinePlanningContext context)
|
||||
{
|
||||
RenderingData planningData =
|
||||
CreatePlanningRenderingData(context);
|
||||
if (planningData == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
BuildPassQueue(planningData);
|
||||
ApplyInferredStandaloneStageRequests(
|
||||
context);
|
||||
|
||||
bool hasPostProcessPass =
|
||||
HasQueuedPassForStage(
|
||||
CameraFrameStage.PostProcess);
|
||||
bool hasFinalOutputPass =
|
||||
HasQueuedPassForStage(
|
||||
CameraFrameStage.FinalOutput);
|
||||
bool needsFinalOutputDependency =
|
||||
context.HasFinalColorProcessing() ||
|
||||
context.IsStageRequested(
|
||||
CameraFrameStage.FinalOutput) ||
|
||||
hasFinalOutputPass;
|
||||
|
||||
if (hasPostProcessPass)
|
||||
{
|
||||
EnsureInferredPostProcessStage(
|
||||
context,
|
||||
needsFinalOutputDependency);
|
||||
}
|
||||
|
||||
if (hasFinalOutputPass &&
|
||||
!context.IsStageRequested(
|
||||
CameraFrameStage.FinalOutput))
|
||||
{
|
||||
context.RequestFullscreenStage(
|
||||
CameraFrameStage.FinalOutput,
|
||||
context.IsStageRequested(
|
||||
CameraFrameStage.PostProcess)
|
||||
? CameraFrameColorSource.PostProcessColor
|
||||
: CameraFrameColorSource.MainSceneColor);
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyInferredStandaloneStageRequests(
|
||||
ScriptableRenderPipelinePlanningContext context)
|
||||
{
|
||||
if (!context.HasExplicitShadowCasterStageConfiguration() &&
|
||||
HasQueuedPassForStage(
|
||||
CameraFrameStage.ShadowCaster))
|
||||
{
|
||||
context.RequestShadowCasterStage();
|
||||
}
|
||||
|
||||
if (!context.HasExplicitDepthOnlyStageConfiguration() &&
|
||||
HasQueuedPassForStage(
|
||||
CameraFrameStage.DepthOnly))
|
||||
{
|
||||
context.RequestDepthOnlyStage();
|
||||
}
|
||||
}
|
||||
|
||||
private bool HasQueuedPassForStage(
|
||||
CameraFrameStage stage)
|
||||
{
|
||||
for (int i = 0; i < m_activePassQueue.Count; ++i)
|
||||
{
|
||||
ScriptableRenderPass renderPass =
|
||||
m_activePassQueue[i];
|
||||
if (renderPass != null &&
|
||||
renderPass.SupportsStage(stage))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void EnsureInferredPostProcessStage(
|
||||
ScriptableRenderPipelinePlanningContext context,
|
||||
bool needsGraphManagedOutputColor)
|
||||
{
|
||||
if (!context.IsStageRequested(
|
||||
CameraFrameStage.PostProcess))
|
||||
{
|
||||
context.RequestFullscreenStage(
|
||||
CameraFrameStage.PostProcess,
|
||||
CameraFrameColorSource.MainSceneColor,
|
||||
needsGraphManagedOutputColor);
|
||||
return;
|
||||
}
|
||||
|
||||
CameraFrameColorSource source =
|
||||
context.GetStageColorSource(
|
||||
CameraFrameStage.PostProcess);
|
||||
if (!needsGraphManagedOutputColor ||
|
||||
source ==
|
||||
CameraFrameColorSource.ExplicitSurface ||
|
||||
context.UsesGraphManagedOutputColor(
|
||||
CameraFrameStage.PostProcess))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
context.ClearFullscreenStage(
|
||||
CameraFrameStage.PostProcess);
|
||||
context.RequestFullscreenStage(
|
||||
CameraFrameStage.PostProcess,
|
||||
source,
|
||||
true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,8 @@ namespace XCEngine.Rendering.Universal
|
||||
: ScriptableObject
|
||||
{
|
||||
public ScriptableRendererFeature[] rendererFeatures;
|
||||
private ScriptableRendererFeature[] m_rendererFeatures;
|
||||
private readonly ScriptableRendererFeatureCollection
|
||||
m_featureCollection;
|
||||
private ScriptableRenderer m_rendererInstance;
|
||||
private bool m_rendererInvalidated;
|
||||
private int m_runtimeStateVersion = 1;
|
||||
@@ -20,6 +21,8 @@ namespace XCEngine.Rendering.Universal
|
||||
{
|
||||
rendererFeatures =
|
||||
Array.Empty<ScriptableRendererFeature>();
|
||||
m_featureCollection =
|
||||
new ScriptableRendererFeatureCollection(this);
|
||||
}
|
||||
|
||||
internal ScriptableRenderer CreateRendererInstance()
|
||||
@@ -60,11 +63,10 @@ namespace XCEngine.Rendering.Universal
|
||||
|
||||
internal void InvalidateRendererFeaturesInstance()
|
||||
{
|
||||
m_rendererFeatureCollectionHash =
|
||||
ComputeRendererFeatureCollectionHash(
|
||||
rendererFeatures ??
|
||||
Array.Empty<ScriptableRendererFeature>());
|
||||
m_rendererFeatureCollectionHashResolved = true;
|
||||
m_featureCollection.Invalidate(
|
||||
ref rendererFeatures,
|
||||
ref m_rendererFeatureCollectionHash,
|
||||
ref m_rendererFeatureCollectionHashResolved);
|
||||
SetDirty();
|
||||
}
|
||||
|
||||
@@ -85,22 +87,9 @@ namespace XCEngine.Rendering.Universal
|
||||
CameraRenderRequestContext context)
|
||||
{
|
||||
ConfigureCameraRenderRequest(context);
|
||||
|
||||
ScriptableRendererFeature[] rendererFeatures =
|
||||
GetRendererFeatures();
|
||||
for (int i = 0; i < rendererFeatures.Length; ++i)
|
||||
{
|
||||
ScriptableRendererFeature rendererFeature =
|
||||
rendererFeatures[i];
|
||||
if (rendererFeature == null ||
|
||||
!rendererFeature.isActive)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
rendererFeature.ConfigureCameraRenderRequest(
|
||||
context);
|
||||
}
|
||||
m_featureCollection.ConfigureCameraRenderRequest(
|
||||
ref rendererFeatures,
|
||||
context);
|
||||
}
|
||||
|
||||
internal void ConfigureCameraFramePlanInstance(
|
||||
@@ -116,21 +105,9 @@ namespace XCEngine.Rendering.Universal
|
||||
context);
|
||||
}
|
||||
|
||||
ScriptableRendererFeature[] rendererFeatures =
|
||||
GetRendererFeatures();
|
||||
for (int i = 0; i < rendererFeatures.Length; ++i)
|
||||
{
|
||||
ScriptableRendererFeature rendererFeature =
|
||||
rendererFeatures[i];
|
||||
if (rendererFeature == null ||
|
||||
!rendererFeature.isActive)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
rendererFeature.ConfigureCameraFramePlan(
|
||||
context);
|
||||
}
|
||||
m_featureCollection.ConfigureCameraFramePlan(
|
||||
ref rendererFeatures,
|
||||
context);
|
||||
|
||||
if (renderer != null)
|
||||
{
|
||||
@@ -152,21 +129,9 @@ namespace XCEngine.Rendering.Universal
|
||||
context);
|
||||
}
|
||||
|
||||
ScriptableRendererFeature[] rendererFeatures =
|
||||
GetRendererFeatures();
|
||||
for (int i = 0; i < rendererFeatures.Length; ++i)
|
||||
{
|
||||
ScriptableRendererFeature rendererFeature =
|
||||
rendererFeatures[i];
|
||||
if (rendererFeature == null ||
|
||||
!rendererFeature.isActive)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
rendererFeature.ConfigureRenderSceneSetup(
|
||||
context);
|
||||
}
|
||||
m_featureCollection.ConfigureRenderSceneSetup(
|
||||
ref rendererFeatures,
|
||||
context);
|
||||
|
||||
return context != null &&
|
||||
context.isConfigured;
|
||||
@@ -187,22 +152,10 @@ namespace XCEngine.Rendering.Universal
|
||||
context);
|
||||
}
|
||||
|
||||
ScriptableRendererFeature[] rendererFeatures =
|
||||
GetRendererFeatures();
|
||||
for (int i = 0; i < rendererFeatures.Length; ++i)
|
||||
{
|
||||
ScriptableRendererFeature rendererFeature =
|
||||
rendererFeatures[i];
|
||||
if (rendererFeature == null ||
|
||||
!rendererFeature.isActive)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
rendererFeature
|
||||
.ConfigureDirectionalShadowExecutionState(
|
||||
context);
|
||||
}
|
||||
m_featureCollection
|
||||
.ConfigureDirectionalShadowExecutionState(
|
||||
ref rendererFeatures,
|
||||
context);
|
||||
|
||||
return context != null &&
|
||||
context.isConfigured;
|
||||
@@ -329,110 +282,25 @@ namespace XCEngine.Rendering.Universal
|
||||
|
||||
protected void ResetRendererFeaturesToDefault()
|
||||
{
|
||||
rendererFeatures =
|
||||
m_featureCollection.Reset(
|
||||
ref rendererFeatures,
|
||||
CreateDefaultRendererFeatures() ??
|
||||
Array.Empty<ScriptableRendererFeature>();
|
||||
BindRendererFeatureOwners(rendererFeatures);
|
||||
Array.Empty<ScriptableRendererFeature>());
|
||||
}
|
||||
|
||||
private ScriptableRendererFeature[] GetRendererFeatures()
|
||||
{
|
||||
if (m_rendererFeatures == null)
|
||||
{
|
||||
ScriptableRendererFeature[]
|
||||
configuredRendererFeatures =
|
||||
rendererFeatures ??
|
||||
Array.Empty<ScriptableRendererFeature>();
|
||||
rendererFeatures =
|
||||
configuredRendererFeatures;
|
||||
m_rendererFeatures =
|
||||
configuredRendererFeatures;
|
||||
}
|
||||
|
||||
BindRendererFeatureOwners(m_rendererFeatures);
|
||||
return m_rendererFeatures;
|
||||
return m_featureCollection.GetFeatures(
|
||||
ref rendererFeatures);
|
||||
}
|
||||
|
||||
private void SynchronizeRendererFeatureCollectionState()
|
||||
{
|
||||
ScriptableRendererFeature[] configuredRendererFeatures =
|
||||
rendererFeatures ??
|
||||
Array.Empty<ScriptableRendererFeature>();
|
||||
BindRendererFeatureOwners(configuredRendererFeatures);
|
||||
|
||||
int collectionHash =
|
||||
ComputeRendererFeatureCollectionHash(
|
||||
configuredRendererFeatures);
|
||||
if (!m_rendererFeatureCollectionHashResolved)
|
||||
{
|
||||
m_rendererFeatureCollectionHash = collectionHash;
|
||||
m_rendererFeatureCollectionHashResolved = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (collectionHash == m_rendererFeatureCollectionHash)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_rendererFeatureCollectionHash = collectionHash;
|
||||
SetDirty();
|
||||
}
|
||||
|
||||
private void BindRendererFeatureOwners(
|
||||
ScriptableRendererFeature[] rendererFeatureCollection)
|
||||
{
|
||||
if (rendererFeatureCollection == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < rendererFeatureCollection.Length; ++i)
|
||||
{
|
||||
ScriptableRendererFeature rendererFeature =
|
||||
rendererFeatureCollection[i];
|
||||
if (rendererFeature != null)
|
||||
{
|
||||
rendererFeature.BindOwnerInstance(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static int ComputeRendererFeatureCollectionHash(
|
||||
ScriptableRendererFeature[] rendererFeatureCollection)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
int hash = 17;
|
||||
if (rendererFeatureCollection == null)
|
||||
{
|
||||
return hash;
|
||||
}
|
||||
|
||||
hash =
|
||||
(hash * 31) +
|
||||
rendererFeatureCollection.Length;
|
||||
for (int i = 0; i < rendererFeatureCollection.Length; ++i)
|
||||
{
|
||||
ScriptableRendererFeature rendererFeature =
|
||||
rendererFeatureCollection[i];
|
||||
if (rendererFeature == null)
|
||||
{
|
||||
hash = (hash * 31) + 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
hash =
|
||||
(hash * 31) +
|
||||
RuntimeHelpers.GetHashCode(rendererFeature);
|
||||
hash =
|
||||
(hash * 31) +
|
||||
rendererFeature
|
||||
.GetRuntimeStateVersionInstance();
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
m_featureCollection.Synchronize(
|
||||
ref rendererFeatures,
|
||||
ref m_rendererFeatureCollectionHash,
|
||||
ref m_rendererFeatureCollectionHashResolved,
|
||||
SetDirty);
|
||||
}
|
||||
|
||||
private void ReleaseRendererSetupCache()
|
||||
@@ -441,26 +309,11 @@ namespace XCEngine.Rendering.Universal
|
||||
{
|
||||
m_rendererInstance.ReleaseRuntimeResourcesInstance();
|
||||
m_rendererInstance = null;
|
||||
m_rendererFeatures = null;
|
||||
m_featureCollection.ResetResolvedCache();
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_rendererFeatures == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < m_rendererFeatures.Length; ++i)
|
||||
{
|
||||
ScriptableRendererFeature rendererFeature =
|
||||
m_rendererFeatures[i];
|
||||
if (rendererFeature != null)
|
||||
{
|
||||
rendererFeature.ReleaseRuntimeResourcesInstance();
|
||||
}
|
||||
}
|
||||
|
||||
m_rendererFeatures = null;
|
||||
m_featureCollection.ReleaseRuntimeResources();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,283 @@
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace XCEngine.Rendering.Universal
|
||||
{
|
||||
internal sealed class ScriptableRendererDataCollection
|
||||
{
|
||||
private ScriptableRendererData[] m_rendererDataList;
|
||||
|
||||
public ScriptableRendererDataCollection()
|
||||
{
|
||||
m_rendererDataList =
|
||||
Array.Empty<ScriptableRendererData>();
|
||||
}
|
||||
|
||||
public ScriptableRendererData GetDefaultRendererData(
|
||||
ref ScriptableRendererData[] configuredRendererDataList,
|
||||
ref int defaultRendererIndex,
|
||||
Func<ScriptableRendererData> createDefaultRendererData)
|
||||
{
|
||||
return GetRendererData(
|
||||
ref configuredRendererDataList,
|
||||
ref defaultRendererIndex,
|
||||
ResolveDefaultRendererIndex(
|
||||
ref configuredRendererDataList,
|
||||
ref defaultRendererIndex,
|
||||
createDefaultRendererData),
|
||||
createDefaultRendererData);
|
||||
}
|
||||
|
||||
public ScriptableRendererData GetRendererData(
|
||||
ref ScriptableRendererData[] configuredRendererDataList,
|
||||
ref int defaultRendererIndex,
|
||||
int rendererIndex,
|
||||
Func<ScriptableRendererData> createDefaultRendererData)
|
||||
{
|
||||
int resolvedRendererIndex =
|
||||
ResolveRendererIndexWithFallback(
|
||||
ref configuredRendererDataList,
|
||||
ref defaultRendererIndex,
|
||||
rendererIndex,
|
||||
createDefaultRendererData);
|
||||
if (resolvedRendererIndex < 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return m_rendererDataList[resolvedRendererIndex];
|
||||
}
|
||||
|
||||
public int ResolveDefaultRendererIndex(
|
||||
ref ScriptableRendererData[] configuredRendererDataList,
|
||||
ref int defaultRendererIndex,
|
||||
Func<ScriptableRendererData> createDefaultRendererData)
|
||||
{
|
||||
ScriptableRendererData[] rendererDataList =
|
||||
ResolveConfiguredRendererDataList(
|
||||
ref configuredRendererDataList,
|
||||
createDefaultRendererData);
|
||||
if (rendererDataList.Length == 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (defaultRendererIndex < 0 ||
|
||||
defaultRendererIndex >= rendererDataList.Length)
|
||||
{
|
||||
defaultRendererIndex = 0;
|
||||
}
|
||||
|
||||
if (rendererDataList[defaultRendererIndex] != null)
|
||||
{
|
||||
return defaultRendererIndex;
|
||||
}
|
||||
|
||||
int firstValidRendererIndex =
|
||||
FindFirstValidRendererIndex(rendererDataList);
|
||||
if (firstValidRendererIndex >= 0)
|
||||
{
|
||||
defaultRendererIndex = firstValidRendererIndex;
|
||||
return defaultRendererIndex;
|
||||
}
|
||||
|
||||
rendererDataList[defaultRendererIndex] =
|
||||
createDefaultRendererData != null
|
||||
? createDefaultRendererData()
|
||||
: null;
|
||||
return rendererDataList[defaultRendererIndex] != null
|
||||
? defaultRendererIndex
|
||||
: -1;
|
||||
}
|
||||
|
||||
public int ResolveRendererIndexWithFallback(
|
||||
ref ScriptableRendererData[] configuredRendererDataList,
|
||||
ref int defaultRendererIndex,
|
||||
int rendererIndex,
|
||||
Func<ScriptableRendererData> createDefaultRendererData)
|
||||
{
|
||||
ScriptableRendererData[] rendererDataList =
|
||||
ResolveConfiguredRendererDataList(
|
||||
ref configuredRendererDataList,
|
||||
createDefaultRendererData);
|
||||
if (rendererDataList.Length == 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (rendererIndex < 0 ||
|
||||
rendererIndex >= rendererDataList.Length)
|
||||
{
|
||||
return ResolveDefaultRendererIndex(
|
||||
ref configuredRendererDataList,
|
||||
ref defaultRendererIndex,
|
||||
createDefaultRendererData);
|
||||
}
|
||||
|
||||
if (rendererDataList[rendererIndex] == null)
|
||||
{
|
||||
return ResolveDefaultRendererIndex(
|
||||
ref configuredRendererDataList,
|
||||
ref defaultRendererIndex,
|
||||
createDefaultRendererData);
|
||||
}
|
||||
|
||||
return rendererIndex;
|
||||
}
|
||||
|
||||
public void Synchronize(
|
||||
ref ScriptableRendererData[] configuredRendererDataList,
|
||||
ref int defaultRendererIndex,
|
||||
ref int collectionHash,
|
||||
ref bool collectionHashResolved,
|
||||
Func<ScriptableRendererData> createDefaultRendererData,
|
||||
Action onChanged)
|
||||
{
|
||||
ScriptableRendererData[] rendererDataList =
|
||||
ResolveConfiguredRendererDataList(
|
||||
ref configuredRendererDataList,
|
||||
createDefaultRendererData);
|
||||
int resolvedDefaultRendererIndex =
|
||||
ResolveDefaultRendererIndex(
|
||||
ref configuredRendererDataList,
|
||||
ref defaultRendererIndex,
|
||||
createDefaultRendererData);
|
||||
int resolvedHash =
|
||||
ComputeCollectionHash(
|
||||
rendererDataList,
|
||||
resolvedDefaultRendererIndex);
|
||||
if (!collectionHashResolved)
|
||||
{
|
||||
collectionHash = resolvedHash;
|
||||
collectionHashResolved = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (resolvedHash == collectionHash)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
collectionHash = resolvedHash;
|
||||
onChanged?.Invoke();
|
||||
}
|
||||
|
||||
public void ReleaseRuntimeResources(
|
||||
ref ScriptableRendererData[] configuredRendererDataList,
|
||||
ref int defaultRendererIndex,
|
||||
Func<ScriptableRendererData> createDefaultRendererData)
|
||||
{
|
||||
ScriptableRendererData[] rendererDataList =
|
||||
ResolveConfiguredRendererDataList(
|
||||
ref configuredRendererDataList,
|
||||
createDefaultRendererData);
|
||||
for (int i = 0; i < rendererDataList.Length; ++i)
|
||||
{
|
||||
ScriptableRendererData rendererData =
|
||||
rendererDataList[i];
|
||||
if (rendererData == null ||
|
||||
WasRendererDataReleasedEarlier(
|
||||
rendererDataList,
|
||||
i))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
rendererData.ReleaseRuntimeResourcesInstance();
|
||||
}
|
||||
}
|
||||
|
||||
private ScriptableRendererData[] ResolveConfiguredRendererDataList(
|
||||
ref ScriptableRendererData[] configuredRendererDataList,
|
||||
Func<ScriptableRendererData> createDefaultRendererData)
|
||||
{
|
||||
if (configuredRendererDataList == null ||
|
||||
configuredRendererDataList.Length == 0)
|
||||
{
|
||||
ScriptableRendererData defaultRendererData =
|
||||
createDefaultRendererData != null
|
||||
? createDefaultRendererData()
|
||||
: null;
|
||||
configuredRendererDataList =
|
||||
defaultRendererData != null
|
||||
? new ScriptableRendererData[]
|
||||
{
|
||||
defaultRendererData
|
||||
}
|
||||
: Array.Empty<ScriptableRendererData>();
|
||||
}
|
||||
|
||||
m_rendererDataList = configuredRendererDataList;
|
||||
return m_rendererDataList;
|
||||
}
|
||||
|
||||
private static int ComputeCollectionHash(
|
||||
ScriptableRendererData[] rendererDataList,
|
||||
int defaultRendererIndex)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
int hash = 17;
|
||||
hash = (hash * 31) + defaultRendererIndex;
|
||||
if (rendererDataList == null)
|
||||
{
|
||||
return hash;
|
||||
}
|
||||
|
||||
hash = (hash * 31) + rendererDataList.Length;
|
||||
for (int i = 0; i < rendererDataList.Length; ++i)
|
||||
{
|
||||
ScriptableRendererData rendererData =
|
||||
rendererDataList[i];
|
||||
if (rendererData == null)
|
||||
{
|
||||
hash = (hash * 31) + 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
hash =
|
||||
(hash * 31) +
|
||||
RuntimeHelpers.GetHashCode(rendererData);
|
||||
hash =
|
||||
(hash * 31) +
|
||||
rendererData.GetRuntimeStateVersionInstance();
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
|
||||
private static int FindFirstValidRendererIndex(
|
||||
ScriptableRendererData[] rendererDataList)
|
||||
{
|
||||
for (int i = 0; i < rendererDataList.Length; ++i)
|
||||
{
|
||||
if (rendererDataList[i] != null)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static bool WasRendererDataReleasedEarlier(
|
||||
ScriptableRendererData[] rendererDataList,
|
||||
int rendererDataIndex)
|
||||
{
|
||||
ScriptableRendererData rendererData =
|
||||
rendererDataList[rendererDataIndex];
|
||||
for (int i = 0; i < rendererDataIndex; ++i)
|
||||
{
|
||||
if (object.ReferenceEquals(
|
||||
rendererDataList[i],
|
||||
rendererData))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,262 @@
|
||||
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<ScriptableRendererFeature>();
|
||||
}
|
||||
|
||||
public ScriptableRendererFeature[] GetFeatures(
|
||||
ref ScriptableRendererFeature[] configuredFeatures)
|
||||
{
|
||||
if (m_features == null)
|
||||
{
|
||||
ScriptableRendererFeature[] resolvedFeatures =
|
||||
configuredFeatures ??
|
||||
Array.Empty<ScriptableRendererFeature>();
|
||||
configuredFeatures = resolvedFeatures;
|
||||
m_features = resolvedFeatures;
|
||||
}
|
||||
|
||||
BindOwners(m_features);
|
||||
return m_features;
|
||||
}
|
||||
|
||||
public void Reset(
|
||||
ref ScriptableRendererFeature[] configuredFeatures,
|
||||
ScriptableRendererFeature[] features)
|
||||
{
|
||||
configuredFeatures =
|
||||
features ??
|
||||
Array.Empty<ScriptableRendererFeature>();
|
||||
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<ScriptableRendererFeature>();
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
using XCEngine;
|
||||
using XCEngine.Rendering;
|
||||
|
||||
namespace XCEngine.Rendering.Universal
|
||||
{
|
||||
internal sealed class UniversalColorScalePostProcessController
|
||||
{
|
||||
private readonly UniversalPostProcessBlock m_postProcessBlock =
|
||||
new UniversalPostProcessBlock();
|
||||
private ColorScalePostProcessPass m_pass;
|
||||
|
||||
public int AppendRuntimeStateHash(
|
||||
int hash,
|
||||
ColorScalePostProcessSettings settings)
|
||||
{
|
||||
return settings != null
|
||||
? settings.AppendRuntimeStateHash(hash)
|
||||
: hash;
|
||||
}
|
||||
|
||||
public void Create(
|
||||
ColorScalePostProcessSettings settings)
|
||||
{
|
||||
if (m_pass == null)
|
||||
{
|
||||
m_pass = new ColorScalePostProcessPass();
|
||||
}
|
||||
|
||||
m_pass.Configure(
|
||||
settings != null
|
||||
? settings.colorScale
|
||||
: new Vector4(
|
||||
1.0f,
|
||||
1.0f,
|
||||
1.0f,
|
||||
1.0f));
|
||||
}
|
||||
|
||||
public void ConfigureCameraFramePlan(
|
||||
ScriptableRenderPipelinePlanningContext context)
|
||||
{
|
||||
m_postProcessBlock.ConfigureCameraFramePlan(
|
||||
context,
|
||||
CameraFrameColorSource.MainSceneColor);
|
||||
}
|
||||
|
||||
public void EnqueuePass(
|
||||
ScriptableRenderer renderer,
|
||||
RenderingData renderingData,
|
||||
ColorScalePostProcessSettings settings)
|
||||
{
|
||||
Create(settings);
|
||||
m_postProcessBlock.EnqueueRenderPass(
|
||||
renderer,
|
||||
renderingData,
|
||||
m_pass);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using XCEngine;
|
||||
|
||||
namespace XCEngine.Rendering.Universal
|
||||
{
|
||||
internal static class UniversalDefaultRendererFeatureFactory
|
||||
{
|
||||
public static ScriptableRendererFeature[]
|
||||
CreateDefaultRendererFeatures()
|
||||
{
|
||||
BuiltinGaussianSplatRendererFeature gaussianSplatFeature =
|
||||
ScriptableObject
|
||||
.CreateInstance<BuiltinGaussianSplatRendererFeature>() ??
|
||||
new BuiltinGaussianSplatRendererFeature();
|
||||
BuiltinVolumetricRendererFeature volumetricFeature =
|
||||
ScriptableObject
|
||||
.CreateInstance<BuiltinVolumetricRendererFeature>() ??
|
||||
new BuiltinVolumetricRendererFeature();
|
||||
return new ScriptableRendererFeature[]
|
||||
{
|
||||
gaussianSplatFeature,
|
||||
volumetricFeature
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
using XCEngine;
|
||||
using XCEngine.Rendering;
|
||||
|
||||
namespace XCEngine.Rendering.Universal
|
||||
{
|
||||
internal sealed class UniversalDepthPrepassBlock
|
||||
{
|
||||
private readonly DrawObjectsPass m_drawDepthPrepass =
|
||||
new DrawObjectsPass(
|
||||
RenderPassEvent.BeforeRenderingPrePasses,
|
||||
SceneRenderPhase.Opaque,
|
||||
RendererListDesc.CreateDefault(
|
||||
RendererListType.Opaque));
|
||||
|
||||
public void ConfigureCameraFramePlan(
|
||||
ScriptableRenderPipelinePlanningContext context,
|
||||
DepthPrepassBlockData depthPrepass)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (depthPrepass != null &&
|
||||
depthPrepass.enabled &&
|
||||
context.RequestCameraDepthOnlyStage())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
context.ClearDepthOnlyStage();
|
||||
}
|
||||
|
||||
public void EnqueueRenderPasses(
|
||||
ScriptableRenderer renderer,
|
||||
DepthPrepassBlockData depthPrepass)
|
||||
{
|
||||
if (renderer == null ||
|
||||
depthPrepass == null ||
|
||||
!depthPrepass.enabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_drawDepthPrepass.Configure(
|
||||
depthPrepass.passEvent,
|
||||
SceneRenderPhase.Opaque,
|
||||
depthPrepass.rendererListDesc,
|
||||
depthPrepass.drawingSettings);
|
||||
renderer.EnqueuePass(m_drawDepthPrepass);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
using XCEngine;
|
||||
using XCEngine.Rendering;
|
||||
|
||||
namespace XCEngine.Rendering.Universal
|
||||
{
|
||||
internal sealed class UniversalFinalOutputBlock
|
||||
{
|
||||
private readonly BuiltinFinalColorPass m_builtinFinalColorPass =
|
||||
new BuiltinFinalColorPass();
|
||||
|
||||
public void FinalizeCameraFramePlan(
|
||||
ScriptableRenderPipelinePlanningContext context,
|
||||
UniversalPostProcessBlock postProcessBlock)
|
||||
{
|
||||
if (context == null ||
|
||||
!context.HasFinalColorProcessing())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
context.ClearFullscreenStage(
|
||||
CameraFrameStage.FinalOutput);
|
||||
|
||||
CameraFrameColorSource finalOutputSource =
|
||||
postProcessBlock != null
|
||||
? postProcessBlock.ResolveFinalOutputSource(
|
||||
context)
|
||||
: CameraFrameColorSource.MainSceneColor;
|
||||
|
||||
context.RequestFullscreenStage(
|
||||
CameraFrameStage.FinalOutput,
|
||||
finalOutputSource);
|
||||
}
|
||||
|
||||
public void EnqueueRenderPasses(
|
||||
ScriptableRenderer renderer,
|
||||
RenderingData renderingData)
|
||||
{
|
||||
if (renderer == null ||
|
||||
renderingData == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!renderingData.isFinalOutputStage &&
|
||||
!renderingData.finalColorData.requiresProcessing)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
renderer.EnqueuePass(m_builtinFinalColorPass);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
using XCEngine;
|
||||
using XCEngine.Rendering;
|
||||
|
||||
namespace XCEngine.Rendering.Universal
|
||||
{
|
||||
internal sealed class UniversalMainSceneBlock
|
||||
{
|
||||
private const string kMainLightShadowsKeyword =
|
||||
"XC_MAIN_LIGHT_SHADOWS";
|
||||
private readonly DrawObjectsPass m_drawOpaqueObjectsPass =
|
||||
new DrawObjectsPass(
|
||||
RenderPassEvent.RenderOpaques,
|
||||
SceneRenderPhase.Opaque,
|
||||
RendererListDesc.CreateDefault(
|
||||
RendererListType.Opaque));
|
||||
private readonly DrawSkyboxPass m_drawSkyboxPass =
|
||||
new DrawSkyboxPass();
|
||||
private readonly DrawObjectsPass m_drawTransparentObjectsPass =
|
||||
new DrawObjectsPass(
|
||||
RenderPassEvent.RenderTransparents,
|
||||
SceneRenderPhase.Transparent,
|
||||
RendererListDesc.CreateDefault(
|
||||
RendererListType.Transparent));
|
||||
|
||||
public void ConfigureRenderSceneSetup(
|
||||
RenderSceneSetupContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
context.SetEnvironmentNone();
|
||||
context.ClearGlobalShaderKeywords();
|
||||
|
||||
Camera camera = context.camera;
|
||||
if (ShouldUseSkyboxEnvironment(
|
||||
context,
|
||||
camera))
|
||||
{
|
||||
if (camera.hasSkyboxMaterial)
|
||||
{
|
||||
context.UseCameraSkyboxMaterial();
|
||||
}
|
||||
else
|
||||
{
|
||||
context.SetProceduralSkybox(
|
||||
camera.skyboxTopColor,
|
||||
camera.skyboxHorizonColor,
|
||||
camera.skyboxBottomColor);
|
||||
}
|
||||
}
|
||||
|
||||
context.SetGlobalShaderKeyword(
|
||||
kMainLightShadowsKeyword,
|
||||
context.hasMainDirectionalShadow);
|
||||
}
|
||||
|
||||
public void EnqueueRenderPasses(
|
||||
ScriptableRenderer renderer,
|
||||
UniversalMainSceneData mainScene)
|
||||
{
|
||||
if (renderer == null ||
|
||||
mainScene == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (mainScene.renderOpaque)
|
||||
{
|
||||
EnqueueOpaquePasses(
|
||||
renderer,
|
||||
mainScene);
|
||||
}
|
||||
|
||||
if (mainScene.renderSkybox)
|
||||
{
|
||||
EnqueueSkyboxPasses(
|
||||
renderer,
|
||||
mainScene);
|
||||
}
|
||||
|
||||
if (mainScene.renderTransparent)
|
||||
{
|
||||
EnqueueTransparentPasses(
|
||||
renderer,
|
||||
mainScene);
|
||||
}
|
||||
}
|
||||
|
||||
private void EnqueueOpaquePasses(
|
||||
ScriptableRenderer renderer,
|
||||
UniversalMainSceneData mainScene)
|
||||
{
|
||||
m_drawOpaqueObjectsPass.Configure(
|
||||
mainScene.opaquePassEvent,
|
||||
SceneRenderPhase.Opaque,
|
||||
mainScene.opaqueRendererListDesc,
|
||||
mainScene.opaqueDrawingSettings);
|
||||
renderer.EnqueuePass(m_drawOpaqueObjectsPass);
|
||||
}
|
||||
|
||||
private void EnqueueSkyboxPasses(
|
||||
ScriptableRenderer renderer,
|
||||
UniversalMainSceneData mainScene)
|
||||
{
|
||||
m_drawSkyboxPass.Configure(
|
||||
mainScene.skyboxPassEvent);
|
||||
renderer.EnqueuePass(m_drawSkyboxPass);
|
||||
}
|
||||
|
||||
private void EnqueueTransparentPasses(
|
||||
ScriptableRenderer renderer,
|
||||
UniversalMainSceneData mainScene)
|
||||
{
|
||||
m_drawTransparentObjectsPass.Configure(
|
||||
mainScene.transparentPassEvent,
|
||||
SceneRenderPhase.Transparent,
|
||||
mainScene.transparentRendererListDesc,
|
||||
mainScene.transparentDrawingSettings);
|
||||
renderer.EnqueuePass(
|
||||
m_drawTransparentObjectsPass);
|
||||
}
|
||||
|
||||
private static bool ShouldUseSkyboxEnvironment(
|
||||
RenderSceneSetupContext context,
|
||||
Camera camera)
|
||||
{
|
||||
if (context == null ||
|
||||
camera == null ||
|
||||
!context.hasMainSceneDepthAttachment ||
|
||||
(context.clearFlags & RenderClearFlags.Color) == 0 ||
|
||||
!camera.skyboxEnabled)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return camera.projectionType ==
|
||||
CameraProjectionType.Perspective;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
using XCEngine;
|
||||
using XCEngine.Rendering;
|
||||
|
||||
namespace XCEngine.Rendering.Universal
|
||||
{
|
||||
internal static class UniversalMainSceneFeatureUtility
|
||||
{
|
||||
public static bool IsActive(
|
||||
RenderingData renderingData)
|
||||
{
|
||||
return renderingData != null &&
|
||||
renderingData.isMainSceneStage;
|
||||
}
|
||||
|
||||
public static bool SupportsPass(
|
||||
RenderingData renderingData,
|
||||
ScriptableRenderPass renderPass)
|
||||
{
|
||||
return IsActive(renderingData) &&
|
||||
renderPass != null &&
|
||||
renderPass.SupportsStage(
|
||||
renderingData.stage);
|
||||
}
|
||||
|
||||
public static bool EnqueuePass(
|
||||
ScriptableRenderer renderer,
|
||||
RenderingData renderingData,
|
||||
ScriptableRenderPass renderPass)
|
||||
{
|
||||
if (renderer == null ||
|
||||
!SupportsPass(
|
||||
renderingData,
|
||||
renderPass))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
renderer.EnqueuePass(renderPass);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
using XCEngine;
|
||||
using XCEngine.Rendering;
|
||||
|
||||
namespace XCEngine.Rendering.Universal
|
||||
{
|
||||
internal sealed class UniversalNativeSceneFeatureController
|
||||
{
|
||||
private readonly NativeSceneFeaturePassId m_featurePassId;
|
||||
private NativeSceneFeaturePass m_pass;
|
||||
|
||||
public UniversalNativeSceneFeatureController(
|
||||
NativeSceneFeaturePassId featurePassId)
|
||||
{
|
||||
m_featurePassId =
|
||||
featurePassId;
|
||||
}
|
||||
|
||||
public int AppendRuntimeStateHash(
|
||||
int hash,
|
||||
RenderPassEvent passEvent)
|
||||
{
|
||||
return RuntimeStateHashUtility.Combine(
|
||||
hash,
|
||||
(int)passEvent);
|
||||
}
|
||||
|
||||
public void Create(
|
||||
RenderPassEvent passEvent)
|
||||
{
|
||||
if (m_pass == null)
|
||||
{
|
||||
m_pass = new NativeSceneFeaturePass(
|
||||
m_featurePassId,
|
||||
passEvent);
|
||||
return;
|
||||
}
|
||||
|
||||
m_pass.Configure(passEvent);
|
||||
}
|
||||
|
||||
public void EnqueuePass(
|
||||
ScriptableRenderer renderer,
|
||||
RenderingData renderingData,
|
||||
RenderPassEvent passEvent)
|
||||
{
|
||||
Create(passEvent);
|
||||
UniversalMainSceneFeatureUtility.EnqueuePass(
|
||||
renderer,
|
||||
renderingData,
|
||||
m_pass);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
using XCEngine;
|
||||
using XCEngine.Rendering;
|
||||
|
||||
namespace XCEngine.Rendering.Universal
|
||||
{
|
||||
internal sealed class UniversalPostProcessBlock
|
||||
{
|
||||
public void ConfigureCameraFramePlan(
|
||||
ScriptableRenderPipelinePlanningContext context,
|
||||
CameraFrameColorSource sourceColor)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bool needsGraphManagedOutputColor =
|
||||
context.HasFinalColorProcessing() ||
|
||||
context.IsStageRequested(
|
||||
CameraFrameStage.FinalOutput);
|
||||
EnsurePostProcessStage(
|
||||
context,
|
||||
sourceColor,
|
||||
needsGraphManagedOutputColor);
|
||||
}
|
||||
|
||||
public CameraFrameColorSource ResolveFinalOutputSource(
|
||||
ScriptableRenderPipelinePlanningContext context)
|
||||
{
|
||||
if (context == null ||
|
||||
!context.IsStageRequested(
|
||||
CameraFrameStage.PostProcess))
|
||||
{
|
||||
return CameraFrameColorSource.MainSceneColor;
|
||||
}
|
||||
|
||||
CameraFrameColorSource postProcessSource =
|
||||
context.GetStageColorSource(
|
||||
CameraFrameStage.PostProcess);
|
||||
if (postProcessSource ==
|
||||
CameraFrameColorSource.ExplicitSurface)
|
||||
{
|
||||
return CameraFrameColorSource.MainSceneColor;
|
||||
}
|
||||
|
||||
PromoteToGraphManagedOutputColor(
|
||||
context);
|
||||
return CameraFrameColorSource.PostProcessColor;
|
||||
}
|
||||
|
||||
public void EnqueueRenderPass(
|
||||
ScriptableRenderer renderer,
|
||||
RenderingData renderingData,
|
||||
ScriptableRenderPass renderPass)
|
||||
{
|
||||
if (renderer == null ||
|
||||
renderingData == null ||
|
||||
renderPass == null ||
|
||||
!renderingData.isPostProcessStage)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
renderer.EnqueuePass(renderPass);
|
||||
}
|
||||
|
||||
private static void EnsurePostProcessStage(
|
||||
ScriptableRenderPipelinePlanningContext context,
|
||||
CameraFrameColorSource sourceColor,
|
||||
bool needsGraphManagedOutputColor)
|
||||
{
|
||||
if (!context.IsStageRequested(
|
||||
CameraFrameStage.PostProcess))
|
||||
{
|
||||
context.RequestFullscreenStage(
|
||||
CameraFrameStage.PostProcess,
|
||||
sourceColor,
|
||||
needsGraphManagedOutputColor);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!needsGraphManagedOutputColor)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
PromoteToGraphManagedOutputColor(
|
||||
context);
|
||||
}
|
||||
|
||||
private static void PromoteToGraphManagedOutputColor(
|
||||
ScriptableRenderPipelinePlanningContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CameraFrameColorSource source =
|
||||
context.GetStageColorSource(
|
||||
CameraFrameStage.PostProcess);
|
||||
if (source ==
|
||||
CameraFrameColorSource.ExplicitSurface ||
|
||||
context.UsesGraphManagedOutputColor(
|
||||
CameraFrameStage.PostProcess))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
context.ClearFullscreenStage(
|
||||
CameraFrameStage.PostProcess);
|
||||
context.RequestFullscreenStage(
|
||||
CameraFrameStage.PostProcess,
|
||||
source,
|
||||
true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
using XCEngine;
|
||||
using XCEngine.Rendering;
|
||||
|
||||
namespace XCEngine.Rendering.Universal
|
||||
{
|
||||
internal sealed class UniversalRenderObjectsFeatureController
|
||||
{
|
||||
private DrawObjectsPass m_pass;
|
||||
|
||||
public int AppendRuntimeStateHash(
|
||||
int hash,
|
||||
RenderObjectsFeatureSettings settings)
|
||||
{
|
||||
return settings != null
|
||||
? settings.AppendRuntimeStateHash(hash)
|
||||
: hash;
|
||||
}
|
||||
|
||||
public void Create(
|
||||
RenderObjectsFeatureSettings settings)
|
||||
{
|
||||
if (settings == null)
|
||||
{
|
||||
settings = new RenderObjectsFeatureSettings();
|
||||
}
|
||||
|
||||
if (m_pass == null)
|
||||
{
|
||||
m_pass =
|
||||
new DrawObjectsPass(
|
||||
settings.passEvent,
|
||||
settings.scenePhase,
|
||||
settings.rendererListDesc,
|
||||
settings.drawingSettings);
|
||||
return;
|
||||
}
|
||||
|
||||
m_pass.Configure(
|
||||
settings.passEvent,
|
||||
settings.scenePhase,
|
||||
settings.rendererListDesc,
|
||||
settings.drawingSettings);
|
||||
}
|
||||
|
||||
public void EnqueuePass(
|
||||
ScriptableRenderer renderer,
|
||||
RenderingData renderingData,
|
||||
RenderObjectsFeatureSettings settings)
|
||||
{
|
||||
Create(settings);
|
||||
UniversalMainSceneFeatureUtility.EnqueuePass(
|
||||
renderer,
|
||||
renderingData,
|
||||
m_pass);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -37,6 +37,32 @@ namespace XCEngine.Rendering.Universal
|
||||
return;
|
||||
}
|
||||
|
||||
FinalColorSettings resolvedFinalColorSettings =
|
||||
GetFinalColorSettingsInstance().settings;
|
||||
bool hasCameraFinalColorOverrides = false;
|
||||
|
||||
Camera camera = context.camera;
|
||||
if (camera != null &&
|
||||
camera.hasFinalColorOverrides)
|
||||
{
|
||||
FinalColorOverrideSettings overrideSettings =
|
||||
camera.GetFinalColorOverrideSettings();
|
||||
if (overrideSettings.HasOverrides())
|
||||
{
|
||||
overrideSettings.ApplyTo(
|
||||
ref resolvedFinalColorSettings);
|
||||
hasCameraFinalColorOverrides = true;
|
||||
}
|
||||
}
|
||||
|
||||
context.SetResolvedFinalColorPolicy(
|
||||
resolvedFinalColorSettings,
|
||||
true,
|
||||
hasCameraFinalColorOverrides);
|
||||
|
||||
context.clearFlags =
|
||||
ResolveRequestClearFlags(context);
|
||||
|
||||
UniversalShadowSettings shadowSettings =
|
||||
GetShadowSettingsInstance();
|
||||
if (!shadowSettings.supportsMainLightShadows)
|
||||
@@ -87,6 +113,42 @@ namespace XCEngine.Rendering.Universal
|
||||
return base.ResolveRendererIndex(context);
|
||||
}
|
||||
|
||||
private static RenderClearFlags ResolveRequestClearFlags(
|
||||
RendererCameraRequestContext context)
|
||||
{
|
||||
Camera camera =
|
||||
context != null
|
||||
? context.camera
|
||||
: null;
|
||||
if (camera == null)
|
||||
{
|
||||
return RenderClearFlags.All;
|
||||
}
|
||||
|
||||
switch (camera.clearMode)
|
||||
{
|
||||
case CameraClearMode.ColorAndDepth:
|
||||
return RenderClearFlags.All;
|
||||
case CameraClearMode.DepthOnly:
|
||||
return RenderClearFlags.Depth;
|
||||
case CameraClearMode.None:
|
||||
return RenderClearFlags.None;
|
||||
case CameraClearMode.Auto:
|
||||
default:
|
||||
if (camera.stackType ==
|
||||
CameraStackType.Overlay)
|
||||
{
|
||||
return context.renderedRequestCount == 0
|
||||
? RenderClearFlags.All
|
||||
: RenderClearFlags.Depth;
|
||||
}
|
||||
|
||||
return context.renderedBaseCameraCount == 0
|
||||
? RenderClearFlags.All
|
||||
: RenderClearFlags.Depth;
|
||||
}
|
||||
}
|
||||
|
||||
private UniversalShadowSettings GetShadowSettingsInstance()
|
||||
{
|
||||
if (shadows == null)
|
||||
|
||||
@@ -6,34 +6,16 @@ namespace XCEngine.Rendering.Universal
|
||||
public sealed class UniversalRenderer : ScriptableRenderer
|
||||
{
|
||||
private readonly UniversalRendererData m_rendererData;
|
||||
private readonly BuiltinFinalColorPass m_builtinFinalColorPass =
|
||||
new BuiltinFinalColorPass();
|
||||
private readonly DrawObjectsPass m_drawShadowCasterPass =
|
||||
new DrawObjectsPass(
|
||||
RenderPassEvent.BeforeRenderingShadows,
|
||||
SceneRenderPhase.Opaque,
|
||||
RendererListDesc.CreateDefault(
|
||||
RendererListType.ShadowCaster));
|
||||
private readonly DrawObjectsPass m_drawDepthPrepass =
|
||||
new DrawObjectsPass(
|
||||
RenderPassEvent.BeforeRenderingPrePasses,
|
||||
SceneRenderPhase.Opaque,
|
||||
RendererListDesc.CreateDefault(
|
||||
RendererListType.Opaque));
|
||||
private readonly DrawObjectsPass m_drawOpaqueObjectsPass =
|
||||
new DrawObjectsPass(
|
||||
RenderPassEvent.RenderOpaques,
|
||||
SceneRenderPhase.Opaque,
|
||||
RendererListDesc.CreateDefault(
|
||||
RendererListType.Opaque));
|
||||
private readonly DrawSkyboxPass m_drawSkyboxPass =
|
||||
new DrawSkyboxPass();
|
||||
private readonly DrawObjectsPass m_drawTransparentObjectsPass =
|
||||
new DrawObjectsPass(
|
||||
RenderPassEvent.RenderTransparents,
|
||||
SceneRenderPhase.Transparent,
|
||||
RendererListDesc.CreateDefault(
|
||||
RendererListType.Transparent));
|
||||
private readonly UniversalShadowCasterBlock m_shadowCasterBlock =
|
||||
new UniversalShadowCasterBlock();
|
||||
private readonly UniversalDepthPrepassBlock m_depthPrepassBlock =
|
||||
new UniversalDepthPrepassBlock();
|
||||
private readonly UniversalMainSceneBlock m_mainSceneBlock =
|
||||
new UniversalMainSceneBlock();
|
||||
private readonly UniversalPostProcessBlock m_postProcessBlock =
|
||||
new UniversalPostProcessBlock();
|
||||
private readonly UniversalFinalOutputBlock m_finalOutputBlock =
|
||||
new UniversalFinalOutputBlock();
|
||||
|
||||
public UniversalRenderer(
|
||||
UniversalRendererData rendererData)
|
||||
@@ -53,10 +35,10 @@ namespace XCEngine.Rendering.Universal
|
||||
return;
|
||||
}
|
||||
|
||||
ConfigureShadowCasterStage(
|
||||
m_shadowCasterBlock.ConfigureCameraFramePlan(
|
||||
context,
|
||||
m_rendererData.GetShadowCasterBlockInstance());
|
||||
ConfigureDepthOnlyStage(
|
||||
m_depthPrepassBlock.ConfigureCameraFramePlan(
|
||||
context,
|
||||
m_rendererData.GetDepthPrepassBlockInstance());
|
||||
}
|
||||
@@ -70,7 +52,9 @@ namespace XCEngine.Rendering.Universal
|
||||
}
|
||||
|
||||
base.FinalizeCameraFramePlan(context);
|
||||
ConfigureFinalOutputStage(context);
|
||||
m_finalOutputBlock.FinalizeCameraFramePlan(
|
||||
context,
|
||||
m_postProcessBlock);
|
||||
}
|
||||
|
||||
protected override void ConfigureRenderSceneSetup(
|
||||
@@ -81,27 +65,22 @@ namespace XCEngine.Rendering.Universal
|
||||
return;
|
||||
}
|
||||
|
||||
context.UseDefaultSceneSetup();
|
||||
m_mainSceneBlock.ConfigureRenderSceneSetup(
|
||||
context);
|
||||
}
|
||||
|
||||
protected override void ConfigureDirectionalShadowExecutionState(
|
||||
DirectionalShadowExecutionContext context)
|
||||
{
|
||||
if (context == null ||
|
||||
!context.hasPlannedMainDirectionalShadow)
|
||||
if (context == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ShadowCasterBlockData shadowCaster =
|
||||
m_rendererData.GetShadowCasterBlockInstance();
|
||||
if (shadowCaster == null ||
|
||||
!shadowCaster.enabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
context.UseDefaultMainDirectionalShadowExecution();
|
||||
m_shadowCasterBlock
|
||||
.ConfigureDirectionalShadowExecutionState(
|
||||
context,
|
||||
m_rendererData.GetShadowCasterBlockInstance());
|
||||
}
|
||||
|
||||
protected override void AddRenderPasses(
|
||||
@@ -112,179 +91,29 @@ namespace XCEngine.Rendering.Universal
|
||||
return;
|
||||
}
|
||||
|
||||
UniversalMainSceneData mainScene =
|
||||
m_rendererData.GetMainSceneInstance();
|
||||
ShadowCasterBlockData shadowCaster =
|
||||
m_rendererData.GetShadowCasterBlockInstance();
|
||||
DepthPrepassBlockData depthPrepass =
|
||||
m_rendererData.GetDepthPrepassBlockInstance();
|
||||
|
||||
if (shadowCaster.enabled)
|
||||
switch (renderingData.stage)
|
||||
{
|
||||
EnqueueShadowCasterPasses(shadowCaster);
|
||||
case CameraFrameStage.ShadowCaster:
|
||||
m_shadowCasterBlock.EnqueueRenderPasses(
|
||||
this,
|
||||
m_rendererData.GetShadowCasterBlockInstance());
|
||||
break;
|
||||
case CameraFrameStage.DepthOnly:
|
||||
m_depthPrepassBlock.EnqueueRenderPasses(
|
||||
this,
|
||||
m_rendererData.GetDepthPrepassBlockInstance());
|
||||
break;
|
||||
case CameraFrameStage.MainScene:
|
||||
m_mainSceneBlock.EnqueueRenderPasses(
|
||||
this,
|
||||
m_rendererData.GetMainSceneInstance());
|
||||
break;
|
||||
case CameraFrameStage.FinalOutput:
|
||||
m_finalOutputBlock.EnqueueRenderPasses(
|
||||
this,
|
||||
renderingData);
|
||||
break;
|
||||
}
|
||||
|
||||
if (depthPrepass.enabled)
|
||||
{
|
||||
EnqueueDepthPrepass(depthPrepass);
|
||||
}
|
||||
|
||||
if (mainScene.renderOpaque)
|
||||
{
|
||||
EnqueueOpaquePasses(mainScene);
|
||||
}
|
||||
|
||||
if (mainScene.renderSkybox)
|
||||
{
|
||||
EnqueueSkyboxPasses(mainScene);
|
||||
}
|
||||
|
||||
if (mainScene.renderTransparent)
|
||||
{
|
||||
EnqueueTransparentPasses(mainScene);
|
||||
}
|
||||
|
||||
EnqueueFinalOutputPasses(renderingData);
|
||||
}
|
||||
|
||||
private void EnqueueShadowCasterPasses(
|
||||
ShadowCasterBlockData shadowCaster)
|
||||
{
|
||||
m_drawShadowCasterPass.Configure(
|
||||
shadowCaster.passEvent,
|
||||
SceneRenderPhase.Opaque,
|
||||
shadowCaster.rendererListDesc,
|
||||
shadowCaster.drawingSettings);
|
||||
EnqueuePass(m_drawShadowCasterPass);
|
||||
}
|
||||
|
||||
private void EnqueueDepthPrepass(
|
||||
DepthPrepassBlockData depthPrepass)
|
||||
{
|
||||
m_drawDepthPrepass.Configure(
|
||||
depthPrepass.passEvent,
|
||||
SceneRenderPhase.Opaque,
|
||||
depthPrepass.rendererListDesc,
|
||||
depthPrepass.drawingSettings);
|
||||
EnqueuePass(m_drawDepthPrepass);
|
||||
}
|
||||
|
||||
private void EnqueueOpaquePasses(
|
||||
UniversalMainSceneData mainScene)
|
||||
{
|
||||
m_drawOpaqueObjectsPass.Configure(
|
||||
mainScene.opaquePassEvent,
|
||||
SceneRenderPhase.Opaque,
|
||||
mainScene.opaqueRendererListDesc,
|
||||
mainScene.opaqueDrawingSettings);
|
||||
EnqueuePass(m_drawOpaqueObjectsPass);
|
||||
}
|
||||
|
||||
private void EnqueueSkyboxPasses(
|
||||
UniversalMainSceneData mainScene)
|
||||
{
|
||||
m_drawSkyboxPass.Configure(
|
||||
mainScene.skyboxPassEvent);
|
||||
EnqueuePass(m_drawSkyboxPass);
|
||||
}
|
||||
|
||||
private void EnqueueTransparentPasses(
|
||||
UniversalMainSceneData mainScene)
|
||||
{
|
||||
m_drawTransparentObjectsPass.Configure(
|
||||
mainScene.transparentPassEvent,
|
||||
SceneRenderPhase.Transparent,
|
||||
mainScene.transparentRendererListDesc,
|
||||
mainScene.transparentDrawingSettings);
|
||||
EnqueuePass(m_drawTransparentObjectsPass);
|
||||
}
|
||||
|
||||
private static void ConfigureShadowCasterStage(
|
||||
ScriptableRenderPipelinePlanningContext context,
|
||||
ShadowCasterBlockData shadowCaster)
|
||||
{
|
||||
if (shadowCaster != null &&
|
||||
shadowCaster.enabled)
|
||||
{
|
||||
context.RequestShadowCasterStage();
|
||||
return;
|
||||
}
|
||||
|
||||
context.ClearShadowCasterStage();
|
||||
}
|
||||
|
||||
private static void ConfigureDepthOnlyStage(
|
||||
ScriptableRenderPipelinePlanningContext context,
|
||||
DepthPrepassBlockData depthPrepass)
|
||||
{
|
||||
if (depthPrepass != null &&
|
||||
depthPrepass.enabled &&
|
||||
context.RequestCameraDepthOnlyStage())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
context.ClearDepthOnlyStage();
|
||||
}
|
||||
|
||||
private static void ConfigureFinalOutputStage(
|
||||
ScriptableRenderPipelinePlanningContext context)
|
||||
{
|
||||
if (!context.HasFinalColorProcessing())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
context.ClearFullscreenStage(
|
||||
CameraFrameStage.FinalOutput);
|
||||
|
||||
CameraFrameColorSource finalOutputSource =
|
||||
CameraFrameColorSource.MainSceneColor;
|
||||
if (context.IsStageRequested(
|
||||
CameraFrameStage.PostProcess))
|
||||
{
|
||||
CameraFrameColorSource postProcessSource =
|
||||
context.GetStageColorSource(
|
||||
CameraFrameStage.PostProcess);
|
||||
if (postProcessSource !=
|
||||
CameraFrameColorSource.ExplicitSurface)
|
||||
{
|
||||
if (!context.UsesGraphManagedOutputColor(
|
||||
CameraFrameStage.PostProcess))
|
||||
{
|
||||
context.ClearFullscreenStage(
|
||||
CameraFrameStage.PostProcess);
|
||||
context.RequestFullscreenStage(
|
||||
CameraFrameStage.PostProcess,
|
||||
postProcessSource,
|
||||
true);
|
||||
}
|
||||
|
||||
finalOutputSource =
|
||||
CameraFrameColorSource.PostProcessColor;
|
||||
}
|
||||
}
|
||||
|
||||
context.RequestFullscreenStage(
|
||||
CameraFrameStage.FinalOutput,
|
||||
finalOutputSource);
|
||||
}
|
||||
|
||||
private void EnqueueFinalOutputPasses(
|
||||
RenderingData renderingData)
|
||||
{
|
||||
if (renderingData == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!renderingData.isFinalOutputStage &&
|
||||
!renderingData.finalColorData.requiresProcessing)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
EnqueuePass(m_builtinFinalColorPass);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,19 +35,8 @@ namespace XCEngine.Rendering.Universal
|
||||
protected override ScriptableRendererFeature[]
|
||||
CreateDefaultRendererFeatures()
|
||||
{
|
||||
BuiltinGaussianSplatRendererFeature gaussianSplatFeature =
|
||||
ScriptableObject
|
||||
.CreateInstance<BuiltinGaussianSplatRendererFeature>() ??
|
||||
new BuiltinGaussianSplatRendererFeature();
|
||||
BuiltinVolumetricRendererFeature volumetricFeature =
|
||||
ScriptableObject
|
||||
.CreateInstance<BuiltinVolumetricRendererFeature>() ??
|
||||
new BuiltinVolumetricRendererFeature();
|
||||
return new ScriptableRendererFeature[]
|
||||
{
|
||||
gaussianSplatFeature,
|
||||
volumetricFeature
|
||||
};
|
||||
return UniversalDefaultRendererFeatureFactory
|
||||
.CreateDefaultRendererFeatures();
|
||||
}
|
||||
|
||||
internal UniversalMainSceneData GetMainSceneInstance()
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user