@forgeax/engine-runtime 0.1.20 → 0.1.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +102 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/__tests__/create-renderer-gpu-pass-timing.unit.test.d.ts +2 -0
- package/dist/__tests__/create-renderer-gpu-pass-timing.unit.test.d.ts.map +1 -0
- package/dist/__tests__/lights-preservation.fixup.test.d.ts +2 -0
- package/dist/__tests__/lights-preservation.fixup.test.d.ts.map +1 -0
- package/dist/__tests__/render-error-exhaustive.test-d.d.ts.map +1 -1
- package/dist/createRenderer.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +2 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +30 -30
- package/src/__tests__/active-camera.unit.test.ts +6 -8
- package/src/__tests__/asset-registry.recursive.spec.ts +1 -1
- package/src/__tests__/clamp-to-last.e2e.browser.test.ts +2 -2
- package/src/__tests__/components.test-d.ts +10 -3
- package/src/__tests__/components.unit.test.ts +13 -7
- package/src/__tests__/create-renderer-assembly.integration.test.ts +24 -0
- package/src/__tests__/create-renderer-gpu-pass-timing.unit.test.ts +32 -0
- package/src/__tests__/createRenderer.browser-no-webgpu.test.ts +66 -0
- package/src/__tests__/dawn/hello-sprite-nineslice-section.dawn.test.ts +9 -1
- package/src/__tests__/dawn/instances-shadow.dawn.test.ts +15 -2
- package/src/__tests__/errors.unit.test.ts +51 -20
- package/src/__tests__/extract-frames-merge.test.ts +48 -40
- package/src/__tests__/extract-skin-mismatch.unit.test.ts +6 -2
- package/src/__tests__/frame-targets-shadow-regression.unit.test.ts +13 -0
- package/src/__tests__/geometry.unit.test.ts +7 -10
- package/src/__tests__/light-gpu-byte-neutral.unit.test.ts +2 -1
- package/src/__tests__/light-snapshot.test-d.ts +8 -0
- package/src/__tests__/lights-preservation.fixup.test.ts +127 -0
- package/src/__tests__/lights.unit.test.ts +75 -2235
- package/src/__tests__/pbr-pipeline.unit.test.ts +6 -1
- package/src/__tests__/pipeline.unit.test.ts +48 -202
- package/src/__tests__/point-light-shadow.browser.test.ts +208 -83
- package/src/__tests__/point-light-shadow.unit.test.ts +61 -4
- package/src/__tests__/render-error-exhaustive.test-d.ts +63 -9
- package/src/__tests__/render-system-mega.test.ts +30 -41
- package/src/__tests__/render-system-record-multi-material-textureview.test.ts +4 -1
- package/src/__tests__/render-system-record-per-submesh-transparency.test.ts +4 -1
- package/src/__tests__/render-system-skin-bg.unit.test.ts +14 -9
- package/src/__tests__/renderer-recover.unit.test.ts +8 -0
- package/src/__tests__/renderer-surface.unit.test.ts +229 -3
- package/src/__tests__/shadow-csm-atlas.test.ts +41 -0
- package/src/__tests__/shadow-csm-component.test.ts +31 -24
- package/src/__tests__/shadow-csm-extract.test.ts +156 -47
- package/src/__tests__/shadow-csm-runtime-vary.dawn.test.ts +72 -0
- package/src/__tests__/shadow-csm-shader.dawn.test.ts +19 -0
- package/src/__tests__/shadow-csm-ubo.test.ts +41 -45
- package/src/__tests__/shadow-csm-viewport.browser.test.ts +29 -0
- package/src/__tests__/shadow-fields-observable.dawn.test.ts +85 -20
- package/src/__tests__/skinned-shadow-mixed.dawn.test.ts +3 -1
- package/src/__tests__/skylight-lazy-projection.test.ts +8 -5
- package/src/__tests__/ssao-bgl.test.ts +10 -16
- package/src/__tests__/ssao-passes.test.ts +19 -2
- package/src/__tests__/systems.unit.test.ts +44 -31
- package/src/__tests__/view-ubo-layout.browser.test.ts +20 -10
- package/src/createRenderer.ts +1 -0
- package/src/index.ts +1 -2
package/README.md
CHANGED
|
@@ -45,6 +45,58 @@ stale receipt is a structured failure rather than an implicit read of the
|
|
|
45
45
|
current frame. Repair the owner named by `error.detail`, then retry the same
|
|
46
46
|
request.
|
|
47
47
|
|
|
48
|
+
## Directional shadow authoring and recovery index
|
|
49
|
+
|
|
50
|
+
The cold-AI entry is `DirectionalLight.shadowFilter`, followed by one read of
|
|
51
|
+
`renderer.inspect().directionalShadow` read. The closed labels are
|
|
52
|
+
`pcf1`, `pcf3`, `pcf5`, `pcssMedium`, and `pcssHigh`; the default is `pcf3`.
|
|
53
|
+
`shadowAngularRadius` is measured in radians, defaults to `0.00465`, and must
|
|
54
|
+
be in `[0.0001, 0.05]`. `maxPenumbraTexels` is a finite integer measured in
|
|
55
|
+
texels, defaults to `32`, and must be in `[1, 64]`. These are Directional
|
|
56
|
+
author facts; Point/Spot `pcfKernelSize` remains a separate contract.
|
|
57
|
+
|
|
58
|
+
The detached `directionalShadow` projection explains the next action without
|
|
59
|
+
reading renderer private state:
|
|
60
|
+
|
|
61
|
+
| Inspection field | AI interpretation |
|
|
62
|
+
|:--|:--|
|
|
63
|
+
| `requested` / `effective` | Author request and admitted profile |
|
|
64
|
+
| `status` | `accepted`, explicit `fallback`, or `rejected` |
|
|
65
|
+
| `fallbackReason` | `webgl2-unsupported`, `rhi-null-structural`, or `candidate-failed` |
|
|
66
|
+
| `lastKnownGood` | Whether the previous admitted profile was retained |
|
|
67
|
+
| `pixelEvidence` | `available` or `not-available`; structural evidence is not pixel proof |
|
|
68
|
+
| `deviceGeneration` / `graphGeneration` | 当前 inspection result 的 generation identity |
|
|
69
|
+
| `cascadeCount`, `mapSize`, `atlasBytes`, `writerPasses`, `blockerTaps`, `filterTapUpperBound`, `seamTapUpperBound` | Bounded CSM and tap-budget facts |
|
|
70
|
+
|
|
71
|
+
For `error.code === 'shadow-invalid-config'`, use the structured properties
|
|
72
|
+
`error.expected`, `error.hint`, and `error.detail.field`, `actual`, `bound`, and
|
|
73
|
+
`reason`. Set the named field to the bound described by `detail`, then retry;
|
|
74
|
+
the prose `error.message` is not an API. For a failed capable candidate, keep
|
|
75
|
+
the `lastKnownGood` projection, repair or rebuild its producer, call
|
|
76
|
+
`renderer.recover()`, and retry the identical draw. WebGL2 may expose only its
|
|
77
|
+
explicit PCF fallback, while RhiNull is structural (`pixelEvidence:
|
|
78
|
+
not-available`); neither state may be rewritten as PCSS support. A
|
|
79
|
+
`not-run` Browser/Dawn/PNG/timing receipt stays `not-run`.
|
|
80
|
+
|
|
81
|
+
The complete author → inspect → recover path is:
|
|
82
|
+
|
|
83
|
+
```ts
|
|
84
|
+
const renderer = (await createRenderer(canvas)).unwrap();
|
|
85
|
+
// Spawn DirectionalLight with a legal shadowFilter and PCSS units first.
|
|
86
|
+
const frame = renderer.draw(request);
|
|
87
|
+
if (!frame.ok) {
|
|
88
|
+
// Read frame.error.code, .expected, .hint, and typed .detail.
|
|
89
|
+
throw frame.error;
|
|
90
|
+
}
|
|
91
|
+
const shadow = renderer.inspect().directionalShadow;
|
|
92
|
+
// Repair the named owner, renderer.recover(), then retry request when needed.
|
|
93
|
+
void shadow;
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
The labels, units, defaults, structured error shape, and fallback vocabulary
|
|
97
|
+
are shared with [`@forgeax/engine-render`](../render/README.md); runtime owns
|
|
98
|
+
host assembly and recovery invocation, not a second Directional schema.
|
|
99
|
+
|
|
48
100
|
## Render happy path
|
|
49
101
|
|
|
50
102
|
`createRenderer -> attach -> draw -> inspect/observe/recover` assembles one
|
|
@@ -56,6 +108,41 @@ named by `error.detail`, rebuild or cold-cook its source, and retry.
|
|
|
56
108
|
> [!IMPORTANT]
|
|
57
109
|
> Runtime is the sole public host-assembly entry for `createRenderer`. It selects browser/backend services, invokes render's internal construction seam, and cleans up partial construction. It does not own scene, skinning, animation, or render-domain APIs.
|
|
58
110
|
|
|
111
|
+
## Standard profile recovery
|
|
112
|
+
|
|
113
|
+
The host exposes one `forgeax::standard` profile. `lightCount` is one of
|
|
114
|
+
`1 | 32 | 256`, `renderPath` is `forward | deferred`, and local finite lights
|
|
115
|
+
are always prepared for the shared Cluster transport. Invalid profile input
|
|
116
|
+
returns `standard-profile-invalid` with `expected`, `hint`, and `detail`; the
|
|
117
|
+
failed transaction keeps the last-known-good profile and device generation.
|
|
118
|
+
|
|
119
|
+
## Point-shadow creation recipe
|
|
120
|
+
|
|
121
|
+
Point shadows stay discoverable through the App recipe while the renderer
|
|
122
|
+
remains the sole owner of atlas admission and frame facts. Install
|
|
123
|
+
`pointShadowPlugin()` beside the existing renderer provider, then preflight a
|
|
124
|
+
caster count and read the detached inspection after a successful frame:
|
|
125
|
+
|
|
126
|
+
```ts
|
|
127
|
+
import { pointShadowPlugin } from '@forgeax/engine-app';
|
|
128
|
+
|
|
129
|
+
// Include this in the same App/Worker plugin list as rendererPlugin(renderer).
|
|
130
|
+
const pointShadow = app.pluginContext.pointShadow;
|
|
131
|
+
const result = pointShadow?.admit(1);
|
|
132
|
+
if (result !== undefined && !result.ok) throw result.error;
|
|
133
|
+
const facts = pointShadow?.inspect();
|
|
134
|
+
void facts?.shadowed;
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
`admit()` returns a structured `PointShadowRecipeError` for missing
|
|
138
|
+
`storageBuffer`, an invalid request, or a count above the renderer's shared
|
|
139
|
+
`ShadowAtlas` capacity. A World without `PointLightShadow` is the real inactive
|
|
140
|
+
case; there is no pseudo-disabled mode. `inspect()` reports `requested`,
|
|
141
|
+
`admitted`, `shadowed`, occupancy, and capacity from the last submitted frame;
|
|
142
|
+
it is not a second shadow registry. Directional CSM remains the renderer's
|
|
143
|
+
separate global path, and Runtime does not create another provider or submit
|
|
144
|
+
path.
|
|
145
|
+
|
|
59
146
|
## Assemble producer features
|
|
60
147
|
|
|
61
148
|
The host receives a heterogeneous list of producer-owned
|
|
@@ -155,6 +242,21 @@ its structured construction error. After construction, `attach`, `draw`,
|
|
|
155
242
|
`inspect`, `observe`, and `recover` remain receipt-bound and `dispose()` is
|
|
156
243
|
idempotent.
|
|
157
244
|
|
|
245
|
+
## GPU pass timing forwarding
|
|
246
|
+
|
|
247
|
+
`CreateRendererOptions.gpuPassTiming` is forwarded unchanged through the
|
|
248
|
+
existing renderer-options projection. Runtime does not request timestamp
|
|
249
|
+
features, create a timing session, retain RHI handles, inspect a pass catalog,
|
|
250
|
+
or change `ProfileCapture`. Use the Render-owned public route: opt in, keep the
|
|
251
|
+
`draw()` `FrameReceipt`, call `observe(receipt, { include: ['timings'] })`, and
|
|
252
|
+
branch on the four statuses and structured `code`/`hint`. The accepted bounded
|
|
253
|
+
contract and recovery path are documented in
|
|
254
|
+
[`packages/render/README.md`](../render/README.md).
|
|
255
|
+
|
|
256
|
+
Membership timing is a separate producer-specific capability. Its records are
|
|
257
|
+
not generic accepted GPU pass evidence and must not become a second runtime
|
|
258
|
+
owner or controller.
|
|
259
|
+
|
|
158
260
|
### Browser backend selection and diagnosis
|
|
159
261
|
|
|
160
262
|
The default browser path prefers native WebGPU and can retry through the
|