feat(render): implement Campaign AR and terrain fidelity
This commit is contained in:
parent
99cf26e00c
commit
7a5f96ede5
368 changed files with 50611 additions and 950 deletions
227
docs/render-packs/README.md
Normal file
227
docs/render-packs/README.md
Normal file
|
|
@ -0,0 +1,227 @@
|
|||
# Render-pack SDK v1
|
||||
|
||||
**Campaign:** Atmospheric Rendering / Shader Packs
|
||||
**Phase id:** **Campaign AR**
|
||||
**Contract version:** `RenderPackApi.Current == 1`
|
||||
|
||||
Render packs are opt-in, declarative graphics extensions. acdream's current
|
||||
retail-faithful renderer is always installed, remains the default and
|
||||
authoritative comparison path, and is restored as one complete transaction
|
||||
when a selected pack cannot run. A
|
||||
pack cannot access Vulkan, renderer internals, gameplay state, world streaming,
|
||||
or physics.
|
||||
|
||||
The public dependency is only
|
||||
`AcDream.Plugin.Abstractions`. Do not reference `AcDream.App`, Silk.NET, or a
|
||||
Vulkan binding. Three buildable external samples cover the API:
|
||||
|
||||
- [`AcDream.RenderPacks.NoOp`](../../samples/AcDream.RenderPacks.NoOp/) is the
|
||||
smallest discovery and activation conformance pack.
|
||||
- [`AcDream.RenderPacks.AtmosphericTier2`](../../samples/AcDream.RenderPacks.AtmosphericTier2/)
|
||||
declares the complete semantic atmospheric executor with deliberately
|
||||
renamed pack-owned IDs, embeds all referenced SPIR-V, and demonstrates
|
||||
moving authored sun-and-moon shadows for terrain, trees, buildings, players, and monsters.
|
||||
- [`AcDream.RenderPacks.ShadowsOnlyTier2`](../../samples/AcDream.RenderPacks.ShadowsOnlyTier2/)
|
||||
demonstrates that Tier 2 is composable: it requests the same selected-celestial
|
||||
caster/receiver semantics without Tier-1 post-processing or volumetric
|
||||
shafts.
|
||||
|
||||
## Quick start
|
||||
|
||||
1. Target `.NET 10` and reference `AcDream.Plugin.Abstractions` with runtime
|
||||
copy disabled. The acdream host supplies that assembly.
|
||||
2. Add [`plugin.json`](plugin-manifest-v1.schema.json), include
|
||||
`"kinds": ["renderPack"]`, and copy it beside the built entry DLL.
|
||||
3. Expose exactly one public, parameterless `IRenderPackPlugin` entry point.
|
||||
4. Construct immutable `RenderPackDescriptor` values and register them from
|
||||
`Register`. Registration must only publish declarations; do not open assets,
|
||||
compile shaders, start threads, or allocate native/GPU resources.
|
||||
5. Supply shader bytes lazily through `IRenderPackAssets.OpenRead`. Asset keys
|
||||
are forward-slash relative logical paths: never rooted, backslash-based, or
|
||||
`.`/`..` traversals.
|
||||
6. Build and run the SDK validator:
|
||||
|
||||
```powershell
|
||||
dotnet build samples/AcDream.RenderPacks.NoOp/AcDream.RenderPacks.NoOp.csproj -c Release
|
||||
dotnet run --project tools/RenderPackValidator/AcDream.Tools.RenderPackValidator.csproj -c Release -- samples/AcDream.RenderPacks.NoOp/bin/Release/net10.0
|
||||
```
|
||||
|
||||
Substitute `AcDream.RenderPacks.AtmosphericTier2` in both paths to validate
|
||||
the complete Tier 2/Tier 2+ example and its embedded shader interfaces.
|
||||
|
||||
The validator executes the managed registration entry point. Use it only on a
|
||||
pack you trust. It loads no App, RHI, or Vulkan assembly and creates no GPU
|
||||
objects. It validates the manifest, v1 declarations, referenced asset keys,
|
||||
SPIR-V stage/entry point and complete v1 binary interface, managed
|
||||
registration, and duplicate pack IDs. Hardware and driver compatibility remain
|
||||
client-side activation checks.
|
||||
|
||||
To launch a visible offline preview of acdream with the built-in Atmospheric
|
||||
pack and a disposable settings profile:
|
||||
|
||||
```powershell
|
||||
.\tools\launch-atmospheric-preview.ps1 -Preset High
|
||||
```
|
||||
|
||||
The preview starts `AcDream.App` with audio disabled, clears inherited
|
||||
`ACDREAM_*` live/automation/diagnostic state for that child, and leaves the
|
||||
user's normal acdream settings untouched. It records the binary identity,
|
||||
selected audio mode, and separate stdout/stderr logs beside the disposable
|
||||
profile. To exercise OpenAL explicitly, add `-EnableAudio`.
|
||||
|
||||
Vertex and fragment asset keys are independent opaque keys; they do not need
|
||||
matching basenames or a host shader-directory stem. On explicit selection the
|
||||
client opens each declared stream, validates it, copies the bytes into the
|
||||
isolated candidate, and creates shader modules from those immutable blobs.
|
||||
The pipeline retains neither the stream nor a path into the plugin directory.
|
||||
Each stage must be little-endian, word-aligned SPIR-V no larger than 16 MiB.
|
||||
|
||||
Shader-visible pack settings are deliberately capped at 64 declarations. The
|
||||
public `PackSettings` binding and value encoding are documented in the
|
||||
[`semantic binding table`](semantic-bindings-v1.md#packsettings-set-3-binding-8-256-bytes).
|
||||
A persisted user override wins the selected preset override, which wins the
|
||||
declaration default. Overrides are stored by stable pack ID plus setting ID;
|
||||
the host validates the selected descriptor's kind, invariant numeric grammar,
|
||||
range, step, and choice list before supplying the resolved scalars. No renderer
|
||||
object is exposed to managed code.
|
||||
|
||||
When a pack is selected, the retained Config page appends its declared
|
||||
Boolean, bounded Float/Integer, and Choice controls under **Graphics
|
||||
Enhancements**. Changing packs replaces only that optional tail; retail's 39
|
||||
authored Config rows remain unchanged. Numeric controls snap to declared bounds
|
||||
and steps, preset changes retain explicit user overrides, and a pack change
|
||||
starts with an empty valid override map for the new stable pack identity.
|
||||
|
||||
## Manifest
|
||||
|
||||
The authoritative machine-readable schema is
|
||||
[`plugin-manifest-v1.schema.json`](plugin-manifest-v1.schema.json).
|
||||
|
||||
| Field | Meaning |
|
||||
|---|---|
|
||||
| `id` | Stable lowercase logical plugin ID. It is persisted and must not be localized or reused. |
|
||||
| `displayName` | User-visible plugin name. |
|
||||
| `version` | Dotted `System.Version`-compatible package version. |
|
||||
| `entryDll` | Safe path beneath the plugin directory to the managed entry DLL. |
|
||||
| `apiVersion` | General `PluginApi` version. v1 is `1`; this is distinct from `RenderPackApi`. |
|
||||
| `dependencies` | Optional plugin IDs that must load first. |
|
||||
| `kinds` | Entry-point kinds. Include `renderPack`; omission means legacy `gameplay` only. A hybrid lists both. |
|
||||
|
||||
Install one plugin directory containing this manifest, the entry DLL, its
|
||||
private managed dependencies, and declared shader assets. Do not redistribute
|
||||
`AcDream.Plugin.Abstractions.dll` in that directory: type identity is shared
|
||||
from the host.
|
||||
|
||||
## Declaration schema
|
||||
|
||||
The C# records in `AcDream.Plugin.Abstractions.Rendering` are the public v1
|
||||
declaration schema. `RenderPackShaderAbi` publishes the corresponding numeric
|
||||
SPIR-V set, binding, block-size, and capacity constants. They are intentionally
|
||||
BCL-only and expose no Vulkan handle.
|
||||
|
||||
| Declaration | What the pack supplies | What the host owns |
|
||||
|---|---|---|
|
||||
| `RenderPackDescriptor` | Identity/version, highest tier, capabilities, resources, passes, replays, variants, presets, settings, atmosphere policy | Validation, candidate creation, activation and fallback |
|
||||
| `RenderResourceDeclaration` | Logical ID, portable format, extent, usage, lifetime, estimated bytes | Images/buffers, allocation, barriers, frame-flight retirement |
|
||||
| `RenderPassDeclaration` | Fixed hook, shader asset keys, semantic inputs, logical resource reads/writes | Render graph order, descriptor layout, pipeline, command recording |
|
||||
| `SceneReplayDeclaration` | One supported replay semantic, caster flags, 1–4 views | Resident caster selection and existing batched submissions |
|
||||
| `PipelineVariantDeclaration` | Base pipeline semantic, shader assets, compatible material flags, inputs | Visibility, mesh/material ownership, fixed renderer state |
|
||||
| `RenderQualityPreset` | Capability requirements, resource/setting overrides, optional execution hints, and p50/p99 CPU/GPU/VRAM ceilings | Availability, explicit selection and stable-boundary swaps |
|
||||
| `RenderSettingDeclaration` | Stable ID, kind, default, bounds/choices | Persistence and conditional Display UI |
|
||||
| `AtmospherePolicyDeclaration` | Ordered sun and selected-light elevation curves plus explicit `activeDayGroup` multipliers | Authored Dereth clock, celestial source, day group, weather and indoor state |
|
||||
|
||||
IDs use `^[a-z][a-z0-9._-]*$`, are case-insensitively unique within each
|
||||
declaration kind, and remain stable across updates. A pack must declare at
|
||||
least one quality preset and at most 64 settings. The SDK ceiling is 256 MiB pack-owned resident GPU
|
||||
memory, 16 MiB per SPIR-V asset, 16,384 pixels per absolute image dimension,
|
||||
256 image layers, and four scene-replay views. A physical device may expose a
|
||||
lower ceiling or reject a preset whose mandatory capabilities are absent.
|
||||
For API v1 the host admits optional pack memory from one eighth of the selected
|
||||
adapter's probed device-local heaps, capped at 256 MiB resident and 512 MiB
|
||||
transient multisample storage. Presets remain listed with exact limit reasons.
|
||||
Auto requires asynchronous timestamps and uses Low when Medium cannot fit. At
|
||||
runtime, Auto alone watches the selected preset's declared inclusive-GPU p99,
|
||||
pack-added CPU p99, and resident-GPU budgets. If Low remains over any of those
|
||||
budgets for 180 stable samples, the whole pack fails safely to acdream's
|
||||
default renderer with the measured and declared limits in the failure reason.
|
||||
Explicit Low remains selectable and is not silently disabled by the Auto
|
||||
performance policy.
|
||||
|
||||
A Tier-2 directional-shadow elevation curve must resolve to exactly zero at
|
||||
and below the authored 0-degree horizon. Every declared non-positive point
|
||||
must therefore have multiplier `0`; if the curve omits an exact 0-degree
|
||||
point, its first positive point must also be `0` so endpoint clamping or
|
||||
interpolation cannot manufacture a below-horizon directional shadow. The host still
|
||||
owns the independent no-selected-light-energy and indoor gates.
|
||||
|
||||
The built-in Atmospheric Low preset preserves the complete directional-shadow
|
||||
caster set (terrain, opaque and alpha-cutout world geometry, and both animated
|
||||
classes). It reduces cost with two 768 x 768 shadow maps and the ordinary
|
||||
six-pass, quarter-resolution separable post chain: sun occlusion, sun rays,
|
||||
bloom downsample, horizontal blur, vertical blur, and filmic composition. It
|
||||
does not remove a caster class or use the fused post-process hint.
|
||||
|
||||
`FusedAtmosphericPostProcess` is an optional external-pack Low-preset execution
|
||||
hint for the standard atmospheric graph; it is not built-in Low behavior. An
|
||||
opting-in shader pack implements the PackPass ABI below: the host feeds scene
|
||||
depth directly to sun rays and asks filmic to evaluate the declared bloom
|
||||
extraction and separable filter while composing the final image. This reduces
|
||||
command recording without disabling rays, bloom, or filmic composition. The
|
||||
host never infers the hint from pack identity; unknown hints, non-Low use, and
|
||||
incomplete standard graphs fail validation.
|
||||
|
||||
`MultiviewDirectionalShadowCascades` is a separate explicit Low-preset
|
||||
execution hint. The opting-in pack must implement three multiview caster
|
||||
variants. The host records one layered directional-depth
|
||||
pass with view mask `0b11`; `gl_ViewIndex` selects the exact two declared Low
|
||||
cascade matrices. Terrain, opaque, and alpha-cutout commands retain their
|
||||
ordinary pipeline, transform, cull, and cutout semantics. The preset must require
|
||||
`MultiviewDirectionalShadowCascades`; unsupported hardware makes that Low preset
|
||||
unavailable before allocation. A zero hint retains ordinary per-cascade passes.
|
||||
|
||||
Resources are declared in execution order: a pass cannot read a pack resource
|
||||
before an earlier pass writes it, and one pass cannot read and write the same
|
||||
resource. `WorldColor`, `SceneDepth`, and other renderer semantics are not pack
|
||||
resources and are named in `SemanticInputs` instead. API v1 exposes four
|
||||
sampled pass-input slots; buffers, `StructuredData`, and storage resources are
|
||||
reserved enum values and are rejected until a public binding contract exists.
|
||||
Colour image arrays are likewise reserved; v1 arrays are directional-depth
|
||||
maps. One declared pass writes at most one attachment. Only `ToneMap` and
|
||||
`AfterToneMapBeforePrivateViewports` may write directly to the host surface
|
||||
without naming a pack resource.
|
||||
|
||||
Every semantic input implies its capability and the descriptor must list that
|
||||
capability as required: world colour, scene depth/normals, authored sun/selected-
|
||||
celestial/day/weather facts, animation transforms, and directional maps cannot
|
||||
be treated as
|
||||
optional after a pass unconditionally declares them.
|
||||
|
||||
## Lifecycle and versioning
|
||||
|
||||
- Discovery calls `Register` but does not open assets or allocate GPU objects.
|
||||
- Installing a pack never selects it. The user selects a pack ID, version, and
|
||||
preset; `acdream default (retail-faithful)` is always available.
|
||||
- The client validates every declaration and selected asset, builds the full
|
||||
candidate beside the active retail graph, then swaps at a frame boundary.
|
||||
- Dispose the registration handle to withdraw the descriptor. The host also
|
||||
withdraws every handle before unloading its collectible plugin context.
|
||||
- `PluginApi` versions the general managed plugin ABI. `RenderPackApi` versions
|
||||
these graphics declarations. Additive enum/record support stays compatible;
|
||||
a breaking contract requires a new render-pack API version and explicit
|
||||
compatibility path.
|
||||
- Persisted identity is pack ID + pack version + preset ID, never list index.
|
||||
User-authored setting strings are keyed by the same stable pack identity and
|
||||
stable setting ID, never declaration or menu index.
|
||||
|
||||
"Device recreation" in the v1 SDK means full teardown of the old renderer,
|
||||
graphics context, and device, followed by construction and capability probing
|
||||
of a fresh context/device. Retail is authoritative until a fresh pack candidate
|
||||
validates and activates. The SDK does not promise live recovery of a pack or
|
||||
renderer after `VK_ERROR_DEVICE_LOST`; that error is terminal to the old device
|
||||
lifetime.
|
||||
|
||||
The complete campaign contract, budgets, and non-goals remain in
|
||||
[`2026-08-21-atmospheric-rendering.md`](../plans/2026-08-21-atmospheric-rendering.md).
|
||||
The public shader-facing contracts are the
|
||||
[`semantic binding table`](semantic-bindings-v1.md) and
|
||||
[`compatibility/failure guide`](compatibility-and-failure-v1.md).
|
||||
Loading…
Add table
Add a link
Reference in a new issue