acdream/docs/render-packs/compatibility-and-failure-v1.md

8.2 KiB

Render-pack compatibility and failure handling v1

Campaign phase id: TBD

Compatibility is a declaration and activation result, not a promise inferred from a GPU brand. The client keeps unsupported packs visible with one exact reason, refuses to select an unavailable preset, and continues rendering the authoritative acdream default (retail-faithful) path.

Author responsibilities

  • Declare every mandatory facility in RequiredCapabilities. Use OptionalCapabilities only when the pack has a deterministic path that does not need it.
  • Gate each preset independently. Low must remain semantically correct; lower shadow resolution or reach rather than silently removing trees, monsters, players, buildings, alpha cutouts, or animated transforms.
  • Keep resource estimates conservative and below the preset and 256 MiB SDK ceilings. The host clamps dimensions and bytes before allocation. Its optional-pack memory policy admits at most one eighth of the selected adapter's probed device-local heap, capped at 256 MiB resident and 512 MiB transient multisample storage; the lower value wins and is printed in an unavailable-preset reason.
  • Use only declared hooks, semantic inputs, resources, scene replays and base pipeline variants. Pack code receives no arbitrary per-frame callback, command buffer, gameplay owner, RHI object, or Vulkan handle.
  • Treat registration as pure declaration publication. OpenRead must return a new readable stream for the exact requested key and must not retain a world generation or borrowed frame state.
  • Ship SPIR-V words little-endian, four-byte aligned, no larger than 16 MiB per asset, and compatible with the published v1 semantic binding ABI. Both the SDK and client validate the binary stage, main entry point, descriptor allowlist, exact uniform/push layouts, and read-only storage contract before pipeline creation. Vertex and fragment keys are independent logical keys; the selected candidate copies their blobs and never resolves them through the host shader directory.
  • Declare no more than 64 settings and keep their descriptor order stable. The set-3/binding-8 shader mapping is positional: a persisted user override wins the selected-preset override, which wins the declaration default. Boolean becomes 0/1, Choice becomes its zero-based choice index, numeric strings use invariant culture, and unused or defensively invalid slots are zero. The selected descriptor validates every user string against kind, range, step, and choices before activation.

Client transaction

  1. Discover the manifest and descriptor without opening assets or constructing GPU objects.
  2. Compare required capabilities and preset ceilings with the active physical device's probed maxImageDimension2D, maxImageArrayLayers, device-local heap bytes, and format/timestamp support. An unsupported pack remains installed and its individual presets remain visible with exact needed-versus-provided reasons.
  3. After explicit selection, validate every referenced asset and shader interface, then build every resource and pipeline in an isolated candidate.
  4. Activate the complete candidate at a stable frame boundary. Until that point retail keeps rendering.
  5. If any step fails, retire the candidate through normal GPU-flight fences, record one stable diagnostic, select acdream default, and do not retry that pack again during the session.

No half-enabled graph is valid. A missing bloom shader does not leave shadows active; a failed shadow pipeline does not leave a world-colour intermediate or stale descriptor alive.

Auto is a logical selector rather than an allocated preset. It requires asynchronous GPU timestamps, starts at Medium when Medium fits, otherwise starts and stays at Low, and never promotes beyond the highest contiguous compatible preset. If Low itself cannot fit, Auto fails safely to Retail and reports the Low limit that failed.

Runtime Auto decisions use the active preset's declared inclusive-GPU p99, pack-added CPU p99, and resident-GPU budgets. An over-budget Medium selection can step down to Low; if Low then remains over any declared limit for 180 stable samples, the host atomically deactivates the complete pack, reports the measured and budget values, and enters FailedToRetail without a retry loop. This performance fallback is Auto-only. Explicit Low remains selectable when only timestamp support is missing and is never silently reduced by removing terrain, trees, buildings, monsters, players, alpha cutouts, or animated casters. The built-in Low preset instead uses two 768 x 768 shadow maps and an unfused six-pass, quarter-resolution separable post chain. An ordinary explicit Low validation, candidate-build, or runtime failure still follows the complete transactional fallback rules above.

Diagnostic categories

Category Example user-facing reason Recovery
Manifest plugin.json does not declare the renderPack kind Correct/reinstall the package
Managed ABI apiVersion 2 is unsupported; this SDK supports 1..1 Use a compatible client or rebuild the pack
Pack ABI requires render-pack API 2; this client supports 1..1 Same as above
Capability requires unsupported capability DirectionalShadowMaps Select a supported preset/device or retail
Declaration Pass 'blur' reads resource 'bloom-a' before it is written Correct the descriptor
User setting user override 'exposure' has invalid Float value '1,5' Correct/remove that stable setting-ID override; retail remains active
Asset asset 'bloom.frag.spv' is not valid SPIR-V Rebuild/reinstall the pack
Shader interface AtmosphericFrame block does not match v1 Recompile against the v1 binding table
Resource ceiling preset 'high' exceeds the pack memory ceiling Reduce the preset declaration
Auto performance Low remained over its declared performance budget for 180 stable samples Complete pack falls back to Retail; select explicit Low only after reviewing the measured limits
Candidate build pipeline creation failed for 'directional-shadow-world-cutout' Driver/asset diagnosis; retail for this session
Runtime/device selected pack failed validation on the fresh device Retail on the fresh renderer for this session; no retry loop
Removal/update selected pack is no longer installed Retail, while retaining the notice

Diagnostics and screenshot metadata record pack ID, pack version, preset ID, compatibility result and fallback reason. Enhanced screenshots are not retail parity evidence.

Update and removal

Pack IDs remain stable across compatible updates; increment PackVersion and manifest version together. A preset or setting ID that persists must keep its meaning. User values are persisted as invariant strings under the selected pack ID and setting ID, so declaration reordering cannot retarget a value. If an update removes or changes a persisted setting incompatibly, selection fails atomically to retail with the unknown/invalid override reason instead of silently applying it elsewhere. If an update removes the selected preset, the client falls back to a compatible declared preset only after explicit policy permits it; otherwise it selects retail. Removing or unloading a pack first withdraws registrations, then retires GPU-flight resources, then releases the collectible load context.

The built-in atmospheric pack's sun-shadow-* setting IDs predate the selected-celestial source contract. They remain stable persisted identifiers; their current labels and semantics apply to directional shadows from whichever authored celestial source the renderer selects.

Reconnect, portal travel, resize and world-generation replacement do not re-register managed packs. Renderer-owned resources are recreated or retired within the same generation/fence rules; pack assets never own gameplay, streaming, collision, or physics lifetime.

For v1, device recreation is not an in-place VK_ERROR_DEVICE_LOST recovery path. The host tears down the complete old renderer, context, and device, then constructs and probes a new context/device. The default retail renderer remains authoritative while the selected pack is validated as a fresh candidate; a failed candidate stays on retail without an automatic retry loop.