@flighthq/scene3d-wgpu 0.3.0-next.1692.f1a7a9a → 0.3.0-next.1702.8973fda

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.
@@ -1,3 +1,4 @@
1
+ export * from './explainWgpuScene3DCoverage';
1
2
  export * from './blinnPhongWgpuMeshMaterialRenderer';
2
3
  export * from './customShaderWgpuMeshMaterialRenderer';
3
4
  export * from './depthWgpuMeshMaterialRenderer';
@@ -1 +1 @@
1
- {"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA,cAAc,sCAAsC,CAAC;AACrD,cAAc,wCAAwC,CAAC;AACvD,cAAc,iCAAiC,CAAC;AAChD,cAAc,mBAAmB,CAAC;AAClC,cAAc,gDAAgD,CAAC;AAC/D,cAAc,uCAAuC,CAAC;AACtD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,oCAAoC,CAAC;AACnD,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AACxC,cAAc,mCAAmC,CAAC;AAClD,cAAc,kCAAkC,CAAC;AACjD,cAAc,kCAAkC,CAAC;AACjD,cAAc,iCAAiC,CAAC;AAChD,cAAc,mCAAmC,CAAC;AAClD,cAAc,mCAAmC,CAAC;AAClD,cAAc,kCAAkC,CAAC;AACjD,cAAc,iDAAiD,CAAC;AAChE,cAAc,uCAAuC,CAAC;AACtD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,iCAAiC,CAAC;AAChD,cAAc,uCAAuC,CAAC;AACtD,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,yBAAyB,CAAC;AACxC,cAAc,wBAAwB,CAAC;AACvC,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qCAAqC,CAAC"}
1
+ {"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA,cAAc,8BAA8B,CAAC;AAC7C,cAAc,sCAAsC,CAAC;AACrD,cAAc,wCAAwC,CAAC;AACvD,cAAc,iCAAiC,CAAC;AAChD,cAAc,mBAAmB,CAAC;AAClC,cAAc,gDAAgD,CAAC;AAC/D,cAAc,uCAAuC,CAAC;AACtD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,oCAAoC,CAAC;AACnD,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AACxC,cAAc,mCAAmC,CAAC;AAClD,cAAc,kCAAkC,CAAC;AACjD,cAAc,kCAAkC,CAAC;AACjD,cAAc,iCAAiC,CAAC;AAChD,cAAc,mCAAmC,CAAC;AAClD,cAAc,mCAAmC,CAAC;AAClD,cAAc,kCAAkC,CAAC;AACjD,cAAc,iDAAiD,CAAC;AAChE,cAAc,uCAAuC,CAAC;AACtD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,iCAAiC,CAAC;AAChD,cAAc,uCAAuC,CAAC;AACtD,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,yBAAyB,CAAC;AACxC,cAAc,wBAAwB,CAAC;AACvC,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qCAAqC,CAAC"}
package/dist/contract.js CHANGED
@@ -1,3 +1,4 @@
1
+ export * from './explainWgpuScene3DCoverage';
1
2
  export * from './blinnPhongWgpuMeshMaterialRenderer';
2
3
  export * from './customShaderWgpuMeshMaterialRenderer';
3
4
  export * from './depthWgpuMeshMaterialRenderer';
@@ -1 +1 @@
1
- {"version":3,"file":"contract.js","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA,cAAc,sCAAsC,CAAC;AACrD,cAAc,wCAAwC,CAAC;AACvD,cAAc,iCAAiC,CAAC;AAChD,cAAc,mBAAmB,CAAC;AAClC,cAAc,gDAAgD,CAAC;AAC/D,cAAc,uCAAuC,CAAC;AACtD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,oCAAoC,CAAC;AACnD,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AACxC,cAAc,mCAAmC,CAAC;AAClD,cAAc,kCAAkC,CAAC;AACjD,cAAc,kCAAkC,CAAC;AACjD,cAAc,iCAAiC,CAAC;AAChD,cAAc,mCAAmC,CAAC;AAClD,cAAc,mCAAmC,CAAC;AAClD,cAAc,kCAAkC,CAAC;AACjD,cAAc,iDAAiD,CAAC;AAChE,cAAc,uCAAuC,CAAC;AACtD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,iCAAiC,CAAC;AAChD,cAAc,uCAAuC,CAAC;AACtD,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,yBAAyB,CAAC;AACxC,cAAc,wBAAwB,CAAC;AACvC,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qCAAqC,CAAC"}
1
+ {"version":3,"file":"contract.js","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA,cAAc,8BAA8B,CAAC;AAC7C,cAAc,sCAAsC,CAAC;AACrD,cAAc,wCAAwC,CAAC;AACvD,cAAc,iCAAiC,CAAC;AAChD,cAAc,mBAAmB,CAAC;AAClC,cAAc,gDAAgD,CAAC;AAC/D,cAAc,uCAAuC,CAAC;AACtD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,oCAAoC,CAAC;AACnD,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AACxC,cAAc,mCAAmC,CAAC;AAClD,cAAc,kCAAkC,CAAC;AACjD,cAAc,kCAAkC,CAAC;AACjD,cAAc,iCAAiC,CAAC;AAChD,cAAc,mCAAmC,CAAC;AAClD,cAAc,mCAAmC,CAAC;AAClD,cAAc,kCAAkC,CAAC;AACjD,cAAc,iDAAiD,CAAC;AAChE,cAAc,uCAAuC,CAAC;AACtD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,iCAAiC,CAAC;AAChD,cAAc,uCAAuC,CAAC;AACtD,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,yBAAyB,CAAC;AACxC,cAAc,wBAAwB,CAAC;AACvC,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qCAAqC,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { Scene3DKindUsage, SceneCoverageEntry, WgpuRenderState } from '@flighthq/types/contract';
2
+ export declare function explainWgpuScene3DCoverage(out: SceneCoverageEntry[], state: WgpuRenderState, usage: Readonly<Scene3DKindUsage>): void;
3
+ export declare function hasWgpuScene3DCoverage(state: WgpuRenderState, usage: Readonly<Scene3DKindUsage>): boolean;
4
+ //# sourceMappingURL=explainWgpuScene3DCoverage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"explainWgpuScene3DCoverage.d.ts","sourceRoot":"","sources":["../src/explainWgpuScene3DCoverage.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAYtG,wBAAgB,0BAA0B,CACxC,GAAG,EAAE,kBAAkB,EAAE,EACzB,KAAK,EAAE,eAAe,EACtB,KAAK,EAAE,QAAQ,CAAC,gBAAgB,CAAC,GAChC,IAAI,CAGN;AAID,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,QAAQ,CAAC,gBAAgB,CAAC,GAAG,OAAO,CAEzG"}
@@ -0,0 +1,81 @@
1
+ import { getWgpuRenderStateRuntime } from '@flighthq/render-wgpu/contract';
2
+ import { resolveModifier } from '@flighthq/shading/contract';
3
+ import { RenderRegistry, SceneCoverage, StandardMaterialKind } from '@flighthq/types/contract';
4
+ import { getWgpuScene3DRuntime } from './wgpuScene3DRuntime';
5
+ // Clears `out`, then reports every kind in `usage` with how well this state is wired for it — satisfied
6
+ // ones included, so one call is a complete manifest. The WebGPU twin of explainGlScene3DCoverage, and
7
+ // the answering half of the scene↔render seam: @flighthq/scene3d says what a document uses, and this —
8
+ // the package that owns the WebGPU registries — says which of those it can serve.
9
+ //
10
+ // Proactive, unlike explainRenderRegistryMisses, which reports what already missed during a frame. Ask
11
+ // this after loading a document and before the first draw, while the answer is still actionable.
12
+ export function explainWgpuScene3DCoverage(out, state, usage) {
13
+ out.length = 0;
14
+ collectWgpuScene3DCoverageGaps(out, state, usage, false);
15
+ }
16
+ // Whether this state can draw every kind `usage` names, counting a fallback as a shortfall — the
17
+ // authored material is not what would appear. Stops at the first shortfall and never allocates.
18
+ export function hasWgpuScene3DCoverage(state, usage) {
19
+ return !collectWgpuScene3DCoverageGaps(null, state, usage, true);
20
+ }
21
+ // The single implementation both tiers read, so the boolean can never disagree with the explanation.
22
+ // `found` counts only real shortfalls, so appending satisfied entries never flips the predicate.
23
+ function collectWgpuScene3DCoverageGaps(out, state, usage, stopAtFirst) {
24
+ let found = false;
25
+ // drawScene3D resolves a subset's material by kind, then falls back to whatever is registered for
26
+ // StandardMaterialKind, then skips the subset. So an unregistered kind may still draw — as the
27
+ // standard material — which is a downgrade worth naming rather than a silence.
28
+ const materials = getWgpuScene3DRuntime(state).materialRegistry;
29
+ const hasStandard = materials.has(StandardMaterialKind);
30
+ for (let i = 0; i < usage.materialKinds.length; i++) {
31
+ const kind = usage.materialKinds[i];
32
+ if (materials.has(kind)) {
33
+ out?.push({ coverage: SceneCoverage.Satisfied, kind, registry: RenderRegistry.MaterialRenderer });
34
+ continue;
35
+ }
36
+ found = true;
37
+ if (stopAtFirst)
38
+ return true;
39
+ out?.push({
40
+ coverage: hasStandard ? SceneCoverage.Fallback : SceneCoverage.Missing,
41
+ kind,
42
+ registry: RenderRegistry.MaterialRenderer,
43
+ });
44
+ }
45
+ // A texture whose source kind has no resolver samples nothing, so the map is simply absent from the
46
+ // draw — the untextured-model failure this seam exists to surface before it reaches a frame.
47
+ const resolvers = getWgpuRenderStateRuntime(state).wgpuTextureResolverRegistry;
48
+ for (let i = 0; i < usage.textureSourceKinds.length; i++) {
49
+ const kind = usage.textureSourceKinds[i];
50
+ if (resolvers?.has(kind) === true) {
51
+ out?.push({ coverage: SceneCoverage.Satisfied, kind, registry: RenderRegistry.TextureResolver });
52
+ continue;
53
+ }
54
+ found = true;
55
+ if (stopAtFirst)
56
+ return true;
57
+ out?.push({ coverage: SceneCoverage.Missing, kind, registry: RenderRegistry.TextureResolver });
58
+ }
59
+ // The shaded compiler assembles base + ordered modifiers into ONE program, so an unregistered snippet
60
+ // does not fail a single lookup — it fails the whole material. A modifier kind is therefore always
61
+ // Missing, never a fallback.
62
+ const snippets = getWgpuScene3DRuntime(state).modifierSnippetRegistry;
63
+ for (let i = 0; i < usage.modifierKinds.length; i++) {
64
+ const kind = usage.modifierKinds[i];
65
+ if (snippets !== null && resolveModifier(snippets, kind) !== null) {
66
+ out?.push({ coverage: SceneCoverage.Satisfied, kind, registry: RenderRegistry.ModifierSnippet });
67
+ continue;
68
+ }
69
+ found = true;
70
+ if (stopAtFirst)
71
+ return true;
72
+ out?.push({ coverage: SceneCoverage.Missing, kind, registry: RenderRegistry.ModifierSnippet });
73
+ }
74
+ // usage.nodeKinds is deliberately NOT checked. The 3D pipeline collects meshes structurally
75
+ // (`geometry != null` in collectVisibleMeshes) rather than through the node-renderer registry, so no
76
+ // 3D node kind is registered against anything and reporting one would send a caller looking for a
77
+ // registrar that does not exist. That the scene reports node kinds anyway is correct — deciding they
78
+ // need nothing is this layer's call, not the scene's.
79
+ return found;
80
+ }
81
+ //# sourceMappingURL=explainWgpuScene3DCoverage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"explainWgpuScene3DCoverage.js","sourceRoot":"","sources":["../src/explainWgpuScene3DCoverage.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flighthq/scene3d-wgpu",
3
- "version": "0.3.0-next.1692.f1a7a9a",
3
+ "version": "0.3.0-next.1702.8973fda",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/flighthq/flight.git",
@@ -36,20 +36,20 @@
36
36
  "clean:dist": "tsx ../../scripts/clean-package-dist.ts"
37
37
  },
38
38
  "dependencies": {
39
- "@flighthq/camera": "0.3.0-next.1692.f1a7a9a",
40
- "@flighthq/color": "0.3.0-next.1692.f1a7a9a",
41
- "@flighthq/geometry": "0.3.0-next.1692.f1a7a9a",
42
- "@flighthq/image": "0.3.0-next.1692.f1a7a9a",
43
- "@flighthq/lighting": "0.3.0-next.1692.f1a7a9a",
44
- "@flighthq/log": "0.3.0-next.1692.f1a7a9a",
45
- "@flighthq/materials": "0.3.0-next.1692.f1a7a9a",
46
- "@flighthq/node": "0.3.0-next.1692.f1a7a9a",
47
- "@flighthq/render": "0.3.0-next.1692.f1a7a9a",
48
- "@flighthq/render-wgpu": "0.3.0-next.1692.f1a7a9a",
49
- "@flighthq/scene3d": "0.3.0-next.1692.f1a7a9a",
50
- "@flighthq/shading": "0.3.0-next.1692.f1a7a9a",
51
- "@flighthq/texture": "0.3.0-next.1692.f1a7a9a",
52
- "@flighthq/types": "0.3.0-next.1692.f1a7a9a"
39
+ "@flighthq/camera": "0.3.0-next.1702.8973fda",
40
+ "@flighthq/color": "0.3.0-next.1702.8973fda",
41
+ "@flighthq/geometry": "0.3.0-next.1702.8973fda",
42
+ "@flighthq/image": "0.3.0-next.1702.8973fda",
43
+ "@flighthq/lighting": "0.3.0-next.1702.8973fda",
44
+ "@flighthq/log": "0.3.0-next.1702.8973fda",
45
+ "@flighthq/materials": "0.3.0-next.1702.8973fda",
46
+ "@flighthq/node": "0.3.0-next.1702.8973fda",
47
+ "@flighthq/render": "0.3.0-next.1702.8973fda",
48
+ "@flighthq/render-wgpu": "0.3.0-next.1702.8973fda",
49
+ "@flighthq/scene3d": "0.3.0-next.1702.8973fda",
50
+ "@flighthq/shading": "0.3.0-next.1702.8973fda",
51
+ "@flighthq/texture": "0.3.0-next.1702.8973fda",
52
+ "@flighthq/types": "0.3.0-next.1702.8973fda"
53
53
  },
54
54
  "devDependencies": {
55
55
  "@flighthq/mesh": "*",
@@ -0,0 +1,137 @@
1
+ import { createBoxMeshGeometry } from '@flighthq/mesh/contract';
2
+ import { addNodeChild } from '@flighthq/node/contract';
3
+ import { createMesh, createScene3D, createScene3DKindUsage, getScene3DKindUsage } from '@flighthq/scene3d/contract';
4
+ import { createRimModifier, createShadedMaterial } from '@flighthq/shading/contract';
5
+ import { createTexture } from '@flighthq/texture/contract';
6
+ import type {
7
+ ImageResourceReference,
8
+ Scene3DKindUsage,
9
+ SceneCoverageEntry,
10
+ WgpuRenderState,
11
+ } from '@flighthq/types/contract';
12
+ import {
13
+ ImageResourceReferenceKind,
14
+ RenderRegistry,
15
+ ResourceResolutionState,
16
+ SceneCoverage,
17
+ StandardMaterialKind,
18
+ } from '@flighthq/types/contract';
19
+ import { describe, expect, it } from 'vitest';
20
+
21
+ import { explainWgpuScene3DCoverage, hasWgpuScene3DCoverage } from './explainWgpuScene3DCoverage';
22
+ import { registerWgpuMeshMaterialRenderer } from './wgpuMeshMaterialRegistry';
23
+ import { makeWgpuScene3DState } from './wgpuScene3DTestHelper';
24
+
25
+ function shadedUsage(withModifier = false): Scene3DKindUsage {
26
+ const ref: ImageResourceReference = {
27
+ bytes: new Uint8Array([1, 2, 3]),
28
+ failure: null,
29
+ kind: ImageResourceReferenceKind.Embedded,
30
+ mimeType: 'image/png',
31
+ state: ResourceResolutionState.Unresolved,
32
+ };
33
+ const material = createShadedMaterial({ diffuseMap: createTexture({ resource: ref }) });
34
+ if (withModifier) material.modifiers = [createRimModifier({ color: 0x49d8ffff, intensity: 0.7, power: 2.4 })];
35
+ const scene = createScene3D();
36
+ scene.resources.push(ref);
37
+ addNodeChild(scene.root, createMesh(createBoxMeshGeometry(), [material]));
38
+ const usage = createScene3DKindUsage();
39
+ getScene3DKindUsage(usage, scene);
40
+ return usage;
41
+ }
42
+
43
+ function entries(state: WgpuRenderState, withModifier = false): SceneCoverageEntry[] {
44
+ const out: SceneCoverageEntry[] = [];
45
+ explainWgpuScene3DCoverage(out, state, shadedUsage(withModifier));
46
+ return out;
47
+ }
48
+
49
+ const renderer = { bind() {}, draw() {} } as never;
50
+
51
+ describe('explainWgpuScene3DCoverage', () => {
52
+ it('reports a bare state as missing both the material renderer and the texture resolver', () => {
53
+ const found = entries(makeWgpuScene3DState().state);
54
+ expect(found).toContainEqual({
55
+ coverage: SceneCoverage.Missing,
56
+ kind: 'ShadedMaterial',
57
+ registry: RenderRegistry.MaterialRenderer,
58
+ });
59
+ expect(found).toContainEqual({
60
+ coverage: SceneCoverage.Missing,
61
+ kind: 'image',
62
+ registry: RenderRegistry.TextureResolver,
63
+ });
64
+ });
65
+
66
+ it('downgrades the material gap to Fallback once a standard renderer can absorb it', () => {
67
+ const { state } = makeWgpuScene3DState();
68
+ registerWgpuMeshMaterialRenderer(state, StandardMaterialKind, renderer);
69
+ expect(entries(state)).toContainEqual({
70
+ coverage: SceneCoverage.Fallback,
71
+ kind: 'ShadedMaterial',
72
+ registry: RenderRegistry.MaterialRenderer,
73
+ });
74
+ });
75
+
76
+ it('reports the material as Satisfied once its own renderer is registered', () => {
77
+ const { state } = makeWgpuScene3DState();
78
+ registerWgpuMeshMaterialRenderer(state, 'ShadedMaterial', renderer);
79
+ expect(entries(state)).toContainEqual({
80
+ coverage: SceneCoverage.Satisfied,
81
+ kind: 'ShadedMaterial',
82
+ registry: RenderRegistry.MaterialRenderer,
83
+ });
84
+ });
85
+
86
+ it('reports an unregistered modifier snippet as Missing, never a fallback', () => {
87
+ // The shaded compiler assembles base + modifiers into one program, so an absent snippet fails the
88
+ // whole material rather than degrading it.
89
+ expect(entries(makeWgpuScene3DState().state, true)).toContainEqual({
90
+ coverage: SceneCoverage.Missing,
91
+ kind: 'RimModifier',
92
+ registry: RenderRegistry.ModifierSnippet,
93
+ });
94
+ });
95
+
96
+ it('never reports a node-kind entry, since 3D collects meshes structurally', () => {
97
+ expect(entries(makeWgpuScene3DState().state).some((e) => e.registry === RenderRegistry.NodeRenderer)).toBe(false);
98
+ });
99
+
100
+ it('clears out, so a repeated call does not accumulate', () => {
101
+ const { state } = makeWgpuScene3DState();
102
+ const usage = shadedUsage();
103
+ const out: SceneCoverageEntry[] = [];
104
+ explainWgpuScene3DCoverage(out, state, usage);
105
+ const first = out.length;
106
+ explainWgpuScene3DCoverage(out, state, usage);
107
+ expect(out).toHaveLength(first);
108
+ });
109
+ });
110
+
111
+ describe('hasWgpuScene3DCoverage', () => {
112
+ it('is false for a bare state and stays false while any kind is unserved', () => {
113
+ expect(hasWgpuScene3DCoverage(makeWgpuScene3DState().state, shadedUsage())).toBe(false);
114
+ });
115
+
116
+ it('counts a standard-material fallback as uncovered, since the authored material would not appear', () => {
117
+ const { state } = makeWgpuScene3DState();
118
+ registerWgpuMeshMaterialRenderer(state, StandardMaterialKind, renderer);
119
+ expect(hasWgpuScene3DCoverage(state, shadedUsage())).toBe(false);
120
+ });
121
+
122
+ it('agrees with the explain tier on the same state, so the two can never disagree', () => {
123
+ const { state } = makeWgpuScene3DState();
124
+ registerWgpuMeshMaterialRenderer(state, 'ShadedMaterial', renderer);
125
+ const usage = shadedUsage();
126
+ const out: SceneCoverageEntry[] = [];
127
+ explainWgpuScene3DCoverage(out, state, usage);
128
+ const gaps = out.filter((e) => e.coverage !== SceneCoverage.Satisfied);
129
+ expect(hasWgpuScene3DCoverage(state, usage)).toBe(gaps.length === 0);
130
+ });
131
+
132
+ it('is true once nothing in the usage is unserved', () => {
133
+ const usage = createScene3DKindUsage();
134
+ getScene3DKindUsage(usage, createScene3D());
135
+ expect(hasWgpuScene3DCoverage(makeWgpuScene3DState().state, usage)).toBe(true);
136
+ });
137
+ });