@forgeax/engine-render 0.1.34 → 0.1.36
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 +69 -3
- package/dist/assembly/device-feature-admission.d.ts +2 -2
- package/dist/assembly/host-contract.d.ts +3 -2
- package/dist/assembly/host-contract.d.ts.map +1 -1
- package/dist/assembly/recovery/renderer-recover.d.ts.map +1 -1
- package/dist/assembly/render-target-host.d.ts +5 -0
- package/dist/assembly/render-target-host.d.ts.map +1 -1
- package/dist/assembly/renderer-facade.d.ts.map +1 -1
- package/dist/assembly/webgpu-renderer.d.ts +1 -0
- package/dist/assembly/webgpu-renderer.d.ts.map +1 -1
- package/dist/assembly/webgpu-vertex-layouts.d.ts.map +1 -1
- package/dist/authoring.mjs +2 -4
- package/dist/authoring.mjs.map +1 -1
- package/dist/chunk-2OZAS3WU.mjs +3489 -0
- package/dist/chunk-2OZAS3WU.mjs.map +1 -0
- package/dist/{chunk-UI5SFODX.mjs → chunk-BZQ4CDRF.mjs} +2338 -1991
- package/dist/chunk-BZQ4CDRF.mjs.map +1 -0
- package/dist/{chunk-MKDIT2EM.mjs → chunk-CJOV2XLO.mjs} +216 -261
- package/dist/chunk-CJOV2XLO.mjs.map +1 -0
- package/dist/chunk-D6WSBXJ2.mjs +1842 -0
- package/dist/chunk-D6WSBXJ2.mjs.map +1 -0
- package/dist/{chunk-HEB564WF.mjs → chunk-DRF6OULX.mjs} +4 -4
- package/dist/{chunk-HEB564WF.mjs.map → chunk-DRF6OULX.mjs.map} +1 -1
- package/dist/{chunk-OCDLEI6I.mjs → chunk-OB5WAFYH.mjs} +117 -5
- package/dist/chunk-OB5WAFYH.mjs.map +1 -0
- package/dist/{chunk-ODZWR6JQ.mjs → chunk-OEYKKMXG.mjs} +2042 -27
- package/dist/chunk-OEYKKMXG.mjs.map +1 -0
- package/dist/chunk-RIPAEGI6.mjs +48 -0
- package/dist/chunk-RIPAEGI6.mjs.map +1 -0
- package/dist/{chunk-ELJFJ2BU.mjs → chunk-X2KA6WHM.mjs} +29 -4
- package/dist/chunk-X2KA6WHM.mjs.map +1 -0
- package/dist/{chunk-BLXGONR2.mjs → chunk-XSFB7XXQ.mjs} +51 -4
- package/dist/chunk-XSFB7XXQ.mjs.map +1 -0
- package/dist/cloud/frame-context.d.ts +2 -2
- package/dist/cloud/frame-context.d.ts.map +1 -1
- package/dist/construct-renderer.mjs +936 -2140
- package/dist/construct-renderer.mjs.map +1 -1
- package/dist/device/device-scope.d.ts.map +1 -1
- package/dist/device/gpu-residency.d.ts +19 -19
- package/dist/device/gpu-residency.d.ts.map +1 -1
- package/dist/errors/render.d.ts +3 -2
- package/dist/errors/render.d.ts.map +1 -1
- package/dist/extract/material-context.d.ts +7 -0
- package/dist/extract/material-context.d.ts.map +1 -0
- package/dist/features/host.d.ts +5 -0
- package/dist/features/host.d.ts.map +1 -1
- package/dist/features/particle-mesh-layout.d.ts +19 -0
- package/dist/features/particle-mesh-layout.d.ts.map +1 -0
- package/dist/features/plan.d.ts +2 -0
- package/dist/features/plan.d.ts.map +1 -1
- package/dist/features/types.d.ts +8 -0
- package/dist/features/types.d.ts.map +1 -1
- package/dist/glyph-text-layout-system.d.ts +1 -1
- package/dist/glyph-text-layout-system.d.ts.map +1 -1
- package/dist/gpu-driven/production-raster.d.ts +1 -1
- package/dist/gpu-driven/production-raster.d.ts.map +1 -1
- package/dist/gpu-driven/shadow-ownership.d.ts +3 -3
- package/dist/gpu-driven/shadow-ownership.d.ts.map +1 -1
- package/dist/gpu-driven/shadow-views.d.ts +1 -1
- package/dist/gpu-driven/shadow-views.d.ts.map +1 -1
- package/dist/gpu-driven/view-gpu.d.ts +1 -1
- package/dist/gpu-driven/view-gpu.d.ts.map +1 -1
- package/dist/ibl/frame-resources.d.ts.map +1 -1
- package/dist/ibl/skylight-bind-group.d.ts +4 -4
- package/dist/ibl/skylight-bind-group.d.ts.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +542 -9
- package/dist/index.mjs.map +1 -1
- package/dist/instances.d.ts +3 -4
- package/dist/instances.d.ts.map +1 -1
- package/dist/internal.mjs +7 -8
- package/dist/internal.mjs.map +1 -1
- package/dist/pbr-pipeline.d.ts +3 -3
- package/dist/pbr-pipeline.d.ts.map +1 -1
- package/dist/pipeline/standard-output/lut-gpu.d.ts +2 -2
- package/dist/pipeline/standard-output/lut-gpu.d.ts.map +1 -1
- package/dist/pipeline/standard-output/resources.d.ts +2 -2
- package/dist/pipeline/standard-output/resources.d.ts.map +1 -1
- package/dist/publication/contract.d.ts +77 -0
- package/dist/publication/contract.d.ts.map +1 -0
- package/dist/publication/dependencies.d.ts +7 -0
- package/dist/publication/dependencies.d.ts.map +1 -0
- package/dist/publication/prepare-geometry.d.ts +9 -0
- package/dist/publication/prepare-geometry.d.ts.map +1 -0
- package/dist/publication/programs.d.ts +5 -0
- package/dist/publication/programs.d.ts.map +1 -0
- package/dist/publication/publisher.d.ts +34 -0
- package/dist/publication/publisher.d.ts.map +1 -0
- package/dist/publication/receiver.d.ts +29 -0
- package/dist/publication/receiver.d.ts.map +1 -0
- package/dist/publication/resource-scope.d.ts +18 -0
- package/dist/publication/resource-scope.d.ts.map +1 -0
- package/dist/publication/targets.d.ts +33 -0
- package/dist/publication/targets.d.ts.map +1 -0
- package/dist/publication/video.d.ts +5 -0
- package/dist/publication/video.d.ts.map +1 -0
- package/dist/record/fold-buckets.d.ts +3 -3
- package/dist/record/fold-buckets.d.ts.map +1 -1
- package/dist/record/frame-snapshot.d.ts +6 -6
- package/dist/record/frame-snapshot.d.ts.map +1 -1
- package/dist/record/frame.d.ts +5 -4
- package/dist/record/frame.d.ts.map +1 -1
- package/dist/record/helpers.d.ts +2 -2
- package/dist/record/helpers.d.ts.map +1 -1
- package/dist/record/main-pass-geometry.d.ts +2 -2
- package/dist/record/main-pass-geometry.d.ts.map +1 -1
- package/dist/record/main-pass-material.d.ts +7 -9
- package/dist/record/main-pass-material.d.ts.map +1 -1
- package/dist/record/main-pass-sprite-draws.d.ts +3 -16
- package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
- package/dist/record/main-pass.d.ts.map +1 -1
- package/dist/record/prepared-material-bindings.d.ts +2 -3
- package/dist/record/prepared-material-bindings.d.ts.map +1 -1
- package/dist/record/render-context.d.ts +4 -2
- package/dist/record/render-context.d.ts.map +1 -1
- package/dist/record/shadow-pass.d.ts +2 -2
- package/dist/record/shadow-pass.d.ts.map +1 -1
- package/dist/record/sprite-instance-buffer.d.ts +31 -0
- package/dist/record/sprite-instance-buffer.d.ts.map +1 -0
- package/dist/record/target-capture-graph.d.ts +19 -0
- package/dist/record/target-capture-graph.d.ts.map +1 -0
- package/dist/record/typed-frame-graph.d.ts +2 -13
- package/dist/record/typed-frame-graph.d.ts.map +1 -1
- package/dist/record/view-ubo.d.ts.map +1 -1
- package/dist/record/volume-params.d.ts +2 -2
- package/dist/record/volume-params.d.ts.map +1 -1
- package/dist/recovery/render-system-candidate.d.ts +5 -12
- package/dist/recovery/render-system-candidate.d.ts.map +1 -1
- package/dist/render-contract.d.ts +4 -1
- package/dist/render-contract.d.ts.map +1 -1
- package/dist/render-system-extract-tail.d.ts.map +1 -1
- package/dist/render-system-extract.d.ts +2 -0
- package/dist/render-system-extract.d.ts.map +1 -1
- package/dist/render-system-presentation.d.ts +2 -2
- package/dist/render-system-presentation.d.ts.map +1 -1
- package/dist/render-system-projections.d.ts +3 -2
- package/dist/render-system-projections.d.ts.map +1 -1
- package/dist/render-system-residency.d.ts +2 -2
- package/dist/render-system-residency.d.ts.map +1 -1
- package/dist/render-system.d.ts +3 -7
- package/dist/render-system.d.ts.map +1 -1
- package/dist/scene/render-scene.d.ts +8 -4
- package/dist/scene/render-scene.d.ts.map +1 -1
- package/dist/scene/render-source.d.ts +42 -0
- package/dist/scene/render-source.d.ts.map +1 -0
- package/dist/scene/source-systems.d.ts +6 -0
- package/dist/scene/source-systems.d.ts.map +1 -0
- package/dist/systems/skin-palette-allocator.d.ts.map +1 -1
- package/dist/systems/skin-palette-types.d.ts +10 -0
- package/dist/systems/skin-palette-types.d.ts.map +1 -1
- package/dist/systems/transparent-dispatch.d.ts +2 -2
- package/dist/systems/transparent-dispatch.d.ts.map +1 -1
- package/dist/systems/transparent-sort-config.d.ts +2 -1
- package/dist/systems/transparent-sort-config.d.ts.map +1 -1
- package/dist/temporal/index.mjs +6 -7
- package/dist/typed-shadow-passes.d.ts.map +1 -1
- package/package.json +21 -21
- package/src/__tests__/auto-exposure-transaction.integration.test.ts +4 -9
- package/src/__tests__/device-feature-admission.unit.test.ts +3 -2
- package/src/__tests__/device-scope-lifecycle.unit.test.ts +26 -0
- package/src/__tests__/gpu-driven-pbr.dawn.test.ts +3 -4
- package/src/__tests__/gpu-driven-production.integration.test.ts +18 -1
- package/src/__tests__/gpu-driven-shadow-views.unit.test.ts +23 -0
- package/src/__tests__/ktx2-basis-gpu-consumer.dawn.test.ts +4 -1
- package/src/__tests__/main-pass-material-medium-selection.unit.test.ts +0 -1
- package/src/__tests__/material-vertex-texture.browser.test.ts +7 -0
- package/src/__tests__/material-vertex-texture.dawn.test.ts +7 -0
- package/src/__tests__/material-vertex-texture.fixture.ts +31 -0
- package/src/__tests__/materials-standard-contract.unit.test.ts +0 -1
- package/src/__tests__/physical-clearcoat.integration.test.ts +23 -23
- package/src/__tests__/physical-material-budget.unit.test.ts +40 -0
- package/src/__tests__/recovery-candidate-prepare.contract.test.ts +5 -0
- package/src/__tests__/render-error-code-owner.test-d.ts +1 -0
- package/src/__tests__/renderer-factory-material-contract.unit.test.ts +107 -5
- package/src/__tests__/runtime-material-program.integration.test.ts +79 -0
- package/src/__tests__/vertex-layouts-ssot.unit.test.ts +23 -3
- package/src/assembly/device-feature-admission.ts +2 -2
- package/src/assembly/host-contract.ts +5 -2
- package/src/assembly/recovery/renderer-recover.ts +9 -0
- package/src/assembly/render-target-host.ts +57 -47
- package/src/assembly/renderer-facade.ts +3 -1
- package/src/assembly/webgpu-ready.ts +1 -1
- package/src/assembly/webgpu-renderer.ts +101 -70
- package/src/assembly/webgpu-vertex-layouts.ts +2 -9
- package/src/cloud/frame-context.ts +2 -2
- package/src/device/device-scope.ts +3 -0
- package/src/device/gpu-residency.ts +26 -25
- package/src/errors/render.ts +3 -1
- package/src/extract/material-context.ts +21 -0
- package/src/features/host.ts +13 -5
- package/src/features/particle-mesh-layout.ts +25 -0
- package/src/features/plan.ts +2 -0
- package/src/features/types.ts +8 -0
- package/src/glyph-text-layout-system.ts +2 -2
- package/src/gpu-driven/production-raster.ts +9 -3
- package/src/gpu-driven/shadow-ownership.ts +3 -3
- package/src/gpu-driven/shadow-views.ts +27 -2
- package/src/gpu-driven/view-gpu.ts +5 -0
- package/src/ibl/frame-resources.ts +0 -1
- package/src/ibl/skylight-bind-group.ts +13 -25
- package/src/index.ts +9 -0
- package/src/instances.ts +9 -6
- package/src/pbr-pipeline.ts +15 -18
- package/src/pipeline/standard-output/lut-gpu.ts +3 -3
- package/src/pipeline/standard-output/resources.ts +2 -2
- package/src/publication/__tests__/derived-geometry.integration.test.ts +177 -0
- package/src/publication/__tests__/features.integration.test.ts +173 -0
- package/src/publication/__tests__/programs.unit.test.ts +25 -0
- package/src/publication/__tests__/publication.integration.test.ts +415 -0
- package/src/publication/__tests__/targets.integration.test.ts +120 -0
- package/src/publication/__tests__/video.browser.test.ts +50 -0
- package/src/publication/contract.ts +104 -0
- package/src/publication/dependencies.ts +54 -0
- package/src/publication/prepare-geometry.ts +94 -0
- package/src/publication/programs.ts +45 -0
- package/src/publication/publisher.ts +645 -0
- package/src/publication/receiver.ts +297 -0
- package/src/publication/resource-scope.ts +31 -0
- package/src/publication/targets.ts +182 -0
- package/src/publication/video.ts +33 -0
- package/src/record/__tests__/material-bg-cache.unit.test.ts +15 -1
- package/src/record/__tests__/prepared-runtime-material.integration.test.ts +134 -0
- package/src/record/__tests__/sprite-material-abi.unit.test.ts +8 -10
- package/src/record/__tests__/video-texture-view.unit.test.ts +9 -9
- package/src/record/fold-buckets.ts +8 -5
- package/src/record/frame-snapshot.ts +6 -6
- package/src/record/frame.ts +87 -28
- package/src/record/helpers.ts +2 -2
- package/src/record/main-pass-geometry.ts +21 -2
- package/src/record/main-pass-material.ts +37 -33
- package/src/record/main-pass-sprite-draws.ts +6 -152
- package/src/record/main-pass.ts +8 -7
- package/src/record/prepared-material-bindings.ts +16 -37
- package/src/record/render-context.ts +4 -2
- package/src/record/shadow-pass.ts +65 -7
- package/src/record/sprite-instance-buffer.ts +155 -0
- package/src/record/target-capture-graph.ts +258 -0
- package/src/record/typed-frame-graph.ts +11 -207
- package/src/record/view-ubo.ts +1 -1
- package/src/record/volume-params.ts +6 -6
- package/src/recovery/render-system-candidate.ts +10 -18
- package/src/render-contract.ts +6 -1
- package/src/render-system-extract-tail.ts +48 -23
- package/src/render-system-extract.ts +11 -2
- package/src/render-system-presentation.ts +2 -2
- package/src/render-system-projections.ts +3 -2
- package/src/render-system-residency.ts +2 -2
- package/src/render-system.ts +82 -54
- package/src/scene/render-scene.ts +110 -100
- package/src/scene/render-source.ts +90 -0
- package/src/scene/source-systems.ts +33 -0
- package/src/systems/skin-palette-allocator.ts +1 -0
- package/src/systems/skin-palette-types.ts +11 -0
- package/src/systems/transparent-dispatch.ts +2 -2
- package/src/systems/transparent-sort-config.ts +3 -1
- package/src/typed-shadow-passes.ts +36 -5
- package/dist/chunk-BLXGONR2.mjs.map +0 -1
- package/dist/chunk-ELJFJ2BU.mjs.map +0 -1
- package/dist/chunk-ILQ5MEZF.mjs +0 -32
- package/dist/chunk-ILQ5MEZF.mjs.map +0 -1
- package/dist/chunk-MKDIT2EM.mjs.map +0 -1
- package/dist/chunk-OCDLEI6I.mjs.map +0 -1
- package/dist/chunk-ODZWR6JQ.mjs.map +0 -1
- package/dist/chunk-RXZ3RGOU.mjs +0 -53
- package/dist/chunk-RXZ3RGOU.mjs.map +0 -1
- package/dist/chunk-SHFUFJ5N.mjs +0 -1781
- package/dist/chunk-SHFUFJ5N.mjs.map +0 -1
- package/dist/chunk-UI5SFODX.mjs.map +0 -1
- package/dist/chunk-UINHLCZA.mjs +0 -2389
- package/dist/chunk-UINHLCZA.mjs.map +0 -1
- package/dist/chunk-WEX45HKH.mjs +0 -1524
- package/dist/chunk-WEX45HKH.mjs.map +0 -1
package/dist/chunk-SHFUFJ5N.mjs
DELETED
|
@@ -1,1781 +0,0 @@
|
|
|
1
|
-
import { LifecycleConstructionError, GpuDrivenPreparationError, RenderTargetDescriptorInvalidError } from './chunk-WEX45HKH.mjs';
|
|
2
|
-
import { ok, err, derive } from '@forgeax/engine-types';
|
|
3
|
-
import '@forgeax/engine-rhi';
|
|
4
|
-
import { vec3 } from '@forgeax/engine-math';
|
|
5
|
-
import { STANDARD_PIPELINE_PARAM_SCHEMA, standardPhysicalTextureFields, STANDARD_PHYSICAL_TEXTURE_FIELDS } from '@forgeax/engine-shader';
|
|
6
|
-
import { deriveVertexLayoutProjection } from '@forgeax/engine-geometry';
|
|
7
|
-
|
|
8
|
-
var DeviceResourceRef = class {
|
|
9
|
-
kind;
|
|
10
|
-
owner;
|
|
11
|
-
generation;
|
|
12
|
-
value;
|
|
13
|
-
constructor(kind, owner, generation, value) {
|
|
14
|
-
this.kind = kind;
|
|
15
|
-
this.owner = owner;
|
|
16
|
-
this.generation = generation;
|
|
17
|
-
this.value = value;
|
|
18
|
-
}
|
|
19
|
-
isCurrent(scope) {
|
|
20
|
-
return scope.accepts(this);
|
|
21
|
-
}
|
|
22
|
-
isStale(scope) {
|
|
23
|
-
return !this.isCurrent(scope);
|
|
24
|
-
}
|
|
25
|
-
};
|
|
26
|
-
function idempotentCleanup(cleanup) {
|
|
27
|
-
let cleaned = false;
|
|
28
|
-
return (value) => {
|
|
29
|
-
if (cleaned) return;
|
|
30
|
-
cleaned = true;
|
|
31
|
-
return cleanup(value);
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
var DeviceScope = class _DeviceScope {
|
|
35
|
-
generation;
|
|
36
|
-
owner;
|
|
37
|
-
parent;
|
|
38
|
-
lifecycleState = "active";
|
|
39
|
-
resources = /* @__PURE__ */ new Map();
|
|
40
|
-
children = [];
|
|
41
|
-
constructor(generation, owner, parent) {
|
|
42
|
-
this.generation = generation;
|
|
43
|
-
this.owner = owner;
|
|
44
|
-
this.parent = parent;
|
|
45
|
-
parent?.children.push(this);
|
|
46
|
-
}
|
|
47
|
-
static create(generation, owner) {
|
|
48
|
-
if (!Number.isSafeInteger(generation) || generation < 0) {
|
|
49
|
-
throw new RangeError("DeviceScope generation must be a non-negative safe integer.");
|
|
50
|
-
}
|
|
51
|
-
if (owner.length === 0) throw new TypeError("DeviceScope owner must not be empty.");
|
|
52
|
-
return new _DeviceScope(generation, owner);
|
|
53
|
-
}
|
|
54
|
-
get state() {
|
|
55
|
-
return this.lifecycleState;
|
|
56
|
-
}
|
|
57
|
-
get childrenSnapshot() {
|
|
58
|
-
return [...this.children];
|
|
59
|
-
}
|
|
60
|
-
/** Create a renderer-owned child scope without exposing a second device owner. */
|
|
61
|
-
createChild(owner) {
|
|
62
|
-
if (this.lifecycleState !== "active") {
|
|
63
|
-
throw new Error("Cannot create a child DeviceScope from an inactive scope.");
|
|
64
|
-
}
|
|
65
|
-
if (owner.length === 0) throw new TypeError("DeviceScope child owner must not be empty.");
|
|
66
|
-
return new _DeviceScope(this.generation, owner, this);
|
|
67
|
-
}
|
|
68
|
-
ref(kind, value) {
|
|
69
|
-
const ref = new DeviceResourceRef(kind, this.owner, this.generation, value);
|
|
70
|
-
this.resources.set(ref, { ref, cleanup: () => void 0 });
|
|
71
|
-
return ref;
|
|
72
|
-
}
|
|
73
|
-
accepts(ref) {
|
|
74
|
-
return this.lifecycleState === "active" && ref.owner === this.owner && ref.generation === this.generation;
|
|
75
|
-
}
|
|
76
|
-
isAlive() {
|
|
77
|
-
return this.lifecycleState === "active";
|
|
78
|
-
}
|
|
79
|
-
resourceDelta() {
|
|
80
|
-
return this.resources.size;
|
|
81
|
-
}
|
|
82
|
-
/** @internal */
|
|
83
|
-
_adopt(kind, value, cleanup) {
|
|
84
|
-
const ref = new DeviceResourceRef(kind, this.owner, this.generation, value);
|
|
85
|
-
this.resources.set(ref, {
|
|
86
|
-
ref,
|
|
87
|
-
cleanup: idempotentCleanup(cleanup)
|
|
88
|
-
});
|
|
89
|
-
return ref;
|
|
90
|
-
}
|
|
91
|
-
/** @internal Remove ownership only after the resource's cleanup succeeded. */
|
|
92
|
-
_release(ref) {
|
|
93
|
-
this.resources.delete(ref);
|
|
94
|
-
}
|
|
95
|
-
/** @internal */
|
|
96
|
-
_clearResources() {
|
|
97
|
-
const resources = [...this.resources.values()];
|
|
98
|
-
this.resources.clear();
|
|
99
|
-
for (const resource of resources.reverse()) {
|
|
100
|
-
try {
|
|
101
|
-
const pending = resource.cleanup(resource.ref.value);
|
|
102
|
-
if (pending instanceof Promise) void pending.catch(() => void 0);
|
|
103
|
-
} catch {
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
return resources;
|
|
107
|
-
}
|
|
108
|
-
/** Mark an active child as retiring without releasing in-flight resources. */
|
|
109
|
-
beginRetire() {
|
|
110
|
-
if (this.lifecycleState === "active") this.lifecycleState = "retiring";
|
|
111
|
-
}
|
|
112
|
-
clearChildren() {
|
|
113
|
-
for (const child of [...this.children].reverse()) {
|
|
114
|
-
child.retire();
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
detachChild(child) {
|
|
118
|
-
const index = this.children.indexOf(child);
|
|
119
|
-
if (index >= 0) this.children.splice(index, 1);
|
|
120
|
-
}
|
|
121
|
-
retire() {
|
|
122
|
-
if (this.lifecycleState !== "active" && this.lifecycleState !== "retiring") return;
|
|
123
|
-
this.lifecycleState = "retiring";
|
|
124
|
-
this.clearChildren();
|
|
125
|
-
this._clearResources();
|
|
126
|
-
this.lifecycleState = "retired";
|
|
127
|
-
}
|
|
128
|
-
abandon() {
|
|
129
|
-
if (this.lifecycleState !== "active") return;
|
|
130
|
-
this.lifecycleState = "abandoned";
|
|
131
|
-
this.clearChildren();
|
|
132
|
-
this._clearResources();
|
|
133
|
-
}
|
|
134
|
-
dispose() {
|
|
135
|
-
if (this.lifecycleState === "disposed") return;
|
|
136
|
-
this.lifecycleState = "disposed";
|
|
137
|
-
this.clearChildren();
|
|
138
|
-
this._clearResources();
|
|
139
|
-
}
|
|
140
|
-
async replace(generation, resources) {
|
|
141
|
-
const replacement = new _DeviceScope(generation, this.owner, this);
|
|
142
|
-
const transaction = new LifecycleTransaction(replacement);
|
|
143
|
-
for (const resource of resources) transaction.add(resource);
|
|
144
|
-
const result = await transaction.commit();
|
|
145
|
-
if (!result.ok) {
|
|
146
|
-
replacement.abandon();
|
|
147
|
-
return result;
|
|
148
|
-
}
|
|
149
|
-
if (!this.isAlive()) {
|
|
150
|
-
replacement.dispose();
|
|
151
|
-
return transaction.failure("dispose");
|
|
152
|
-
}
|
|
153
|
-
this.detachChild(replacement);
|
|
154
|
-
this.retire();
|
|
155
|
-
return ok(replacement);
|
|
156
|
-
}
|
|
157
|
-
/** @internal */
|
|
158
|
-
_receipt() {
|
|
159
|
-
return {
|
|
160
|
-
owner: this.owner,
|
|
161
|
-
generation: this.generation,
|
|
162
|
-
resourceCount: this.resources.size
|
|
163
|
-
};
|
|
164
|
-
}
|
|
165
|
-
};
|
|
166
|
-
var LifecycleTransaction = class {
|
|
167
|
-
constructor(scope, options = {}) {
|
|
168
|
-
this.scope = scope;
|
|
169
|
-
this.options = options;
|
|
170
|
-
}
|
|
171
|
-
scope;
|
|
172
|
-
resources = [];
|
|
173
|
-
options;
|
|
174
|
-
committed = false;
|
|
175
|
-
add(spec) {
|
|
176
|
-
if (this.committed) throw new Error("LifecycleTransaction is already committed.");
|
|
177
|
-
this.resources.push(spec);
|
|
178
|
-
return this;
|
|
179
|
-
}
|
|
180
|
-
async commit() {
|
|
181
|
-
if (this.committed) return this.failure("create");
|
|
182
|
-
this.committed = true;
|
|
183
|
-
const created = [];
|
|
184
|
-
for (let index = 0; index < this.resources.length; index += 1) {
|
|
185
|
-
const spec = this.resources[index];
|
|
186
|
-
if (spec === void 0) continue;
|
|
187
|
-
try {
|
|
188
|
-
if (this.options.failureAt === index + 1) {
|
|
189
|
-
throw new Error(`injected lifecycle failure at ${index + 1}`);
|
|
190
|
-
}
|
|
191
|
-
const value = await spec.create();
|
|
192
|
-
if (!this.scope.isAlive()) {
|
|
193
|
-
await this.cleanupOne(value, created, idempotentCleanup(spec.cleanup));
|
|
194
|
-
return this.failure("dispose");
|
|
195
|
-
}
|
|
196
|
-
created.push({ spec, value, cleanup: idempotentCleanup(spec.cleanup) });
|
|
197
|
-
} catch (cause) {
|
|
198
|
-
const cleanupFailures = await this.cleanupCreated(created);
|
|
199
|
-
return this.failure("create", spec.kind, cleanupFailures, cause);
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
if (!this.scope.isAlive()) {
|
|
203
|
-
const cleanupFailures = await this.cleanupCreated(created);
|
|
204
|
-
return this.failure("dispose", this.resources.at(-1)?.kind ?? "listener", cleanupFailures);
|
|
205
|
-
}
|
|
206
|
-
for (const item of created) this.scope._adopt(item.spec.kind, item.value, item.spec.cleanup);
|
|
207
|
-
return ok(this.scope);
|
|
208
|
-
}
|
|
209
|
-
failure(operation, resourceKind = this.resources.at(-1)?.kind ?? "listener", cleanupFailures = [], cause = void 0) {
|
|
210
|
-
return err({
|
|
211
|
-
primary: new LifecycleConstructionError({
|
|
212
|
-
owner: this.scope.owner,
|
|
213
|
-
generation: this.scope.generation,
|
|
214
|
-
operation,
|
|
215
|
-
resourceKind,
|
|
216
|
-
cause,
|
|
217
|
-
cleanupFailures,
|
|
218
|
-
receipt: this.scope._receipt()
|
|
219
|
-
}),
|
|
220
|
-
cleanupFailures,
|
|
221
|
-
receipt: this.scope._receipt()
|
|
222
|
-
});
|
|
223
|
-
}
|
|
224
|
-
async cleanupCreated(created) {
|
|
225
|
-
const failures = [];
|
|
226
|
-
for (let index = created.length - 1; index >= 0; index -= 1) {
|
|
227
|
-
const item = created[index];
|
|
228
|
-
if (item === void 0) continue;
|
|
229
|
-
try {
|
|
230
|
-
await item.cleanup(item.value);
|
|
231
|
-
} catch (cause) {
|
|
232
|
-
failures.push({ resourceKind: item.spec.kind, cause });
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
return failures;
|
|
236
|
-
}
|
|
237
|
-
async cleanupOne(value, created, cleanup) {
|
|
238
|
-
await this.cleanupCreated(created);
|
|
239
|
-
try {
|
|
240
|
-
await cleanup(value);
|
|
241
|
-
} catch {
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
};
|
|
245
|
-
|
|
246
|
-
// src/gpu-usage.ts
|
|
247
|
-
var GPU_BUFFER_USAGE_VERTEX = 32;
|
|
248
|
-
var GPU_BUFFER_USAGE_INDEX = 16;
|
|
249
|
-
var GPU_BUFFER_USAGE_COPY_DST = 8;
|
|
250
|
-
var GPU_BUFFER_USAGE_COPY_SRC = 4;
|
|
251
|
-
var GPU_BUFFER_USAGE_UNIFORM = 64;
|
|
252
|
-
var GPU_BUFFER_USAGE_STORAGE = 128;
|
|
253
|
-
var GPU_BUFFER_USAGE_INDIRECT = 256;
|
|
254
|
-
var GPU_BUFFER_USAGE_MAP_READ = 1;
|
|
255
|
-
var GPU_BUFFER_USAGE_QUERY_RESOLVE = 512;
|
|
256
|
-
|
|
257
|
-
// src/prepare/extended-lighting/resources.ts
|
|
258
|
-
var EXTENDED_LIGHTING_TOPOLOGY = "extendedLighting";
|
|
259
|
-
var IES_SLICE_CAPACITY = 32;
|
|
260
|
-
var COOKIE_SLICE_CAPACITY = 32;
|
|
261
|
-
var IES_SLICE_WIDTH = 256;
|
|
262
|
-
var IES_SLICE_HEIGHT = 128;
|
|
263
|
-
var COOKIE_SLICE_SIZE = 256;
|
|
264
|
-
var COOKIE_MATRIX_BYTES = 32 * 16 * Float32Array.BYTES_PER_ELEMENT;
|
|
265
|
-
var EXTENDED_LIGHTING_REQUIRED_SAMPLED_TEXTURES = 21;
|
|
266
|
-
function extendedLightingSampledTextureCapacityAvailable(maxSampledTexturesPerShaderStage) {
|
|
267
|
-
return maxSampledTexturesPerShaderStage !== void 0 && maxSampledTexturesPerShaderStage >= EXTENDED_LIGHTING_REQUIRED_SAMPLED_TEXTURES;
|
|
268
|
-
}
|
|
269
|
-
function deriveExtendedLightingCapability(device) {
|
|
270
|
-
const maxSampledTextures = device.limits.maxSampledTexturesPerShaderStage;
|
|
271
|
-
if (!extendedLightingSampledTextureCapacityAvailable(maxSampledTextures)) {
|
|
272
|
-
return {
|
|
273
|
-
admitted: false,
|
|
274
|
-
topology: EXTENDED_LIGHTING_TOPOLOGY,
|
|
275
|
-
reason: `maxSampledTexturesPerShaderStage ${maxSampledTextures ?? 0} < ${EXTENDED_LIGHTING_REQUIRED_SAMPLED_TEXTURES}`
|
|
276
|
-
};
|
|
277
|
-
}
|
|
278
|
-
const maxLayers = device.limits.maxTextureArrayLayers ?? 0;
|
|
279
|
-
const maxUniformBuffers = device.limits.maxUniformBuffersPerShaderStage ?? 0;
|
|
280
|
-
if (maxLayers < IES_SLICE_CAPACITY) {
|
|
281
|
-
return {
|
|
282
|
-
admitted: false,
|
|
283
|
-
topology: EXTENDED_LIGHTING_TOPOLOGY,
|
|
284
|
-
reason: `maxTextureArrayLayers ${maxLayers} < ${IES_SLICE_CAPACITY}`
|
|
285
|
-
};
|
|
286
|
-
}
|
|
287
|
-
if (maxUniformBuffers < 1) {
|
|
288
|
-
return {
|
|
289
|
-
admitted: false,
|
|
290
|
-
topology: EXTENDED_LIGHTING_TOPOLOGY,
|
|
291
|
-
reason: `maxUniformBuffersPerShaderStage ${maxUniformBuffers} < 1`
|
|
292
|
-
};
|
|
293
|
-
}
|
|
294
|
-
if (!device.caps.storageBuffer || !device.caps.rgba16floatRenderable || !device.caps.samplerAliasing) {
|
|
295
|
-
return {
|
|
296
|
-
admitted: false,
|
|
297
|
-
topology: EXTENDED_LIGHTING_TOPOLOGY,
|
|
298
|
-
reason: "required storage-buffer, rgba16float, or sampler capability is unavailable"
|
|
299
|
-
};
|
|
300
|
-
}
|
|
301
|
-
return { admitted: true, topology: EXTENDED_LIGHTING_TOPOLOGY, reason: void 0 };
|
|
302
|
-
}
|
|
303
|
-
function worldEntityKey(worldId, entityKey) {
|
|
304
|
-
return worldId * 4294967296 + entityKey;
|
|
305
|
-
}
|
|
306
|
-
function instanceCollectionCacheKey(worldId, instance) {
|
|
307
|
-
return -(4294967296 + worldEntityKey(worldId, instance.collectionId ?? instance.cacheKey));
|
|
308
|
-
}
|
|
309
|
-
var ZERO_CAMERA_CLEAR_FALLBACK = [0, 0, 0, 1];
|
|
310
|
-
var textureIdentities = /* @__PURE__ */ new WeakMap();
|
|
311
|
-
var nextTextureIdentity = 1;
|
|
312
|
-
var opaqueResourceIdentities = /* @__PURE__ */ new WeakMap();
|
|
313
|
-
var nextOpaqueResourceIdentity = 1;
|
|
314
|
-
function getOpaqueResourceIdentity(resource) {
|
|
315
|
-
const existing = opaqueResourceIdentities.get(resource);
|
|
316
|
-
if (existing !== void 0) return existing;
|
|
317
|
-
const identity = nextOpaqueResourceIdentity++;
|
|
318
|
-
opaqueResourceIdentities.set(resource, identity);
|
|
319
|
-
return identity;
|
|
320
|
-
}
|
|
321
|
-
function getTextureIdentity(texture) {
|
|
322
|
-
const object = texture;
|
|
323
|
-
const existing = textureIdentities.get(object);
|
|
324
|
-
if (existing !== void 0) return existing;
|
|
325
|
-
const identity = nextTextureIdentity++;
|
|
326
|
-
textureIdentities.set(object, identity);
|
|
327
|
-
return identity;
|
|
328
|
-
}
|
|
329
|
-
function validateGraphTargetCaptureReadback(input) {
|
|
330
|
-
const { bytes, expectedByteLength, sentinel, allowZero = false } = input;
|
|
331
|
-
if (bytes.byteLength !== expectedByteLength)
|
|
332
|
-
return { ok: false, code: "capture-readback-length" };
|
|
333
|
-
if (sentinel?.every((value, index2) => bytes[index2] === value)) {
|
|
334
|
-
return { ok: false, code: "capture-readback-untouched-sentinel" };
|
|
335
|
-
}
|
|
336
|
-
if (!allowZero && bytes.every((value) => value === 0)) {
|
|
337
|
-
return { ok: false, code: "capture-readback-empty" };
|
|
338
|
-
}
|
|
339
|
-
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
340
|
-
let index = 0;
|
|
341
|
-
for (; index + 3 < bytes.byteLength; index += 4) {
|
|
342
|
-
const word = view.getUint32(index, true);
|
|
343
|
-
if ((word & 31744) === 31744 || (word & 2080374784) === 2080374784)
|
|
344
|
-
return { ok: false, code: "capture-readback-non-finite" };
|
|
345
|
-
}
|
|
346
|
-
if (index + 1 < bytes.byteLength && (view.getUint16(index, true) & 31744) === 31744)
|
|
347
|
-
return { ok: false, code: "capture-readback-non-finite" };
|
|
348
|
-
return { ok: true };
|
|
349
|
-
}
|
|
350
|
-
function makeZeroCameraFallbackSnapshot() {
|
|
351
|
-
const identityWorld = new Float32Array(16);
|
|
352
|
-
identityWorld[0] = 1;
|
|
353
|
-
identityWorld[5] = 1;
|
|
354
|
-
identityWorld[10] = 1;
|
|
355
|
-
identityWorld[15] = 1;
|
|
356
|
-
return {
|
|
357
|
-
position: vec3.create(0, 0, 0),
|
|
358
|
-
world: identityWorld,
|
|
359
|
-
fov: Math.PI / 4,
|
|
360
|
-
aspect: 1,
|
|
361
|
-
near: 0.1,
|
|
362
|
-
far: 100,
|
|
363
|
-
// feat-20260613 M6 / w20: synthetic camera defaults to perspective so
|
|
364
|
-
// the CSM extract path stays consistent with the previously-implicit
|
|
365
|
-
// perspective shape (unchanged behavior; explicit field).
|
|
366
|
-
projection: "perspective",
|
|
367
|
-
orthoLeft: -1,
|
|
368
|
-
orthoRight: 1,
|
|
369
|
-
orthoBottom: -1,
|
|
370
|
-
orthoTop: 1,
|
|
371
|
-
tonemap: "none",
|
|
372
|
-
exposure: 1,
|
|
373
|
-
whitePoint: 4,
|
|
374
|
-
antialias: "none",
|
|
375
|
-
bloom: "off",
|
|
376
|
-
bloomThreshold: 1,
|
|
377
|
-
bloomIntensity: 1,
|
|
378
|
-
bloomSoftKnee: 0.5,
|
|
379
|
-
bloomScatter: 0.7,
|
|
380
|
-
clearColor: ZERO_CAMERA_CLEAR_FALLBACK
|
|
381
|
-
};
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
// src/temporal/coverage.ts
|
|
385
|
-
function createTemporalCoverage(width, height) {
|
|
386
|
-
if (!Number.isSafeInteger(width) || width <= 0) throw new RangeError("width must be positive.");
|
|
387
|
-
if (!Number.isSafeInteger(height) || height <= 0)
|
|
388
|
-
throw new RangeError("height must be positive.");
|
|
389
|
-
return Object.freeze({ width, height, bytes: 34 * width * height, fullScreen: true });
|
|
390
|
-
}
|
|
391
|
-
function classifySceneDataCoverage(input) {
|
|
392
|
-
const exactContributorIds = input.contributors.filter((c) => c.kind === "exact").map((c) => c.id);
|
|
393
|
-
const reactiveContributorIds = input.contributors.filter((c) => c.kind === "reactive").map((c) => c.id);
|
|
394
|
-
const available = new Set(input.contributors.map((c) => c.id));
|
|
395
|
-
const missing = input.requiredContributorIds.filter((id) => !available.has(id));
|
|
396
|
-
return {
|
|
397
|
-
exactContributorIds: Object.freeze(exactContributorIds),
|
|
398
|
-
reactiveContributorIds: Object.freeze(reactiveContributorIds),
|
|
399
|
-
missingContributorIds: Object.freeze(missing.slice(0, 32)),
|
|
400
|
-
omittedMissingContributorCount: Math.max(0, missing.length - 32),
|
|
401
|
-
complete: missing.length === 0
|
|
402
|
-
};
|
|
403
|
-
}
|
|
404
|
-
function scanSceneDataCoverage(input) {
|
|
405
|
-
const classification = classifySceneDataCoverage({
|
|
406
|
-
contributors: input.contributorIds.map((id) => ({ id, kind: "exact" })),
|
|
407
|
-
requiredContributorIds: input.requiredContributorIds
|
|
408
|
-
});
|
|
409
|
-
return Object.freeze({
|
|
410
|
-
schema: input.schema,
|
|
411
|
-
lane: input.lane,
|
|
412
|
-
producerId: input.producerId,
|
|
413
|
-
...classification,
|
|
414
|
-
contributorIds: Object.freeze([...input.contributorIds])
|
|
415
|
-
});
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
// src/gpu-stage.ts
|
|
419
|
-
var GPU_SHADER_STAGE_VERTEX = 1;
|
|
420
|
-
var GPU_SHADER_STAGE_FRAGMENT = 2;
|
|
421
|
-
var GPU_SHADER_STAGE_COMPUTE = 4;
|
|
422
|
-
var BGL_ONLY_SPEC_STUB = Object.freeze({
|
|
423
|
-
shader: { id: "", passKind: "forward", variantSet: void 0 },
|
|
424
|
-
attachments: { colorFormats: [], depthFormat: void 0, sampleCount: 1 },
|
|
425
|
-
geometry: { topology: "triangle-list", vertexLayout: {} },
|
|
426
|
-
renderState: void 0
|
|
427
|
-
});
|
|
428
|
-
function buildPbrMaterialUserRegionEntries(paramSchema = STANDARD_PIPELINE_PARAM_SCHEMA, excludedTextureFields = []) {
|
|
429
|
-
const excluded = new Set(excludedTextureFields);
|
|
430
|
-
for (const field of standardPhysicalTextureFields(paramSchema)) excluded.add(field);
|
|
431
|
-
const derived = derive(
|
|
432
|
-
excluded.size === 0 ? paramSchema : paramSchema.filter(
|
|
433
|
-
(entry) => !excluded.has(entry.name) || !entry.type.startsWith("texture")
|
|
434
|
-
)
|
|
435
|
-
);
|
|
436
|
-
let entries = derived.bglEntries.map(
|
|
437
|
-
(entry) => ({
|
|
438
|
-
binding: entry.binding,
|
|
439
|
-
visibility: entry.visibility,
|
|
440
|
-
...entry.buffer === void 0 ? {} : { buffer: entry.buffer },
|
|
441
|
-
...entry.sampler === void 0 ? {} : { sampler: entry.sampler },
|
|
442
|
-
...entry.texture === void 0 ? {} : { texture: entry.texture },
|
|
443
|
-
...entry.storageTexture === void 0 ? {} : { storageTexture: entry.storageTexture }
|
|
444
|
-
})
|
|
445
|
-
);
|
|
446
|
-
const ubo = entries[0];
|
|
447
|
-
if (ubo !== void 0 && ubo.binding === 0 && ubo.buffer?.type === "uniform") {
|
|
448
|
-
entries[0] = {
|
|
449
|
-
binding: 0,
|
|
450
|
-
visibility: GPU_SHADER_STAGE_VERTEX | GPU_SHADER_STAGE_FRAGMENT,
|
|
451
|
-
buffer: { type: "uniform", hasDynamicOffset: true }
|
|
452
|
-
};
|
|
453
|
-
} else {
|
|
454
|
-
entries = [
|
|
455
|
-
{
|
|
456
|
-
binding: 0,
|
|
457
|
-
visibility: GPU_SHADER_STAGE_VERTEX | GPU_SHADER_STAGE_FRAGMENT,
|
|
458
|
-
buffer: { type: "uniform", hasDynamicOffset: true }
|
|
459
|
-
},
|
|
460
|
-
...entries.map((entry) => ({ ...entry, binding: entry.binding + 1 }))
|
|
461
|
-
];
|
|
462
|
-
}
|
|
463
|
-
return entries;
|
|
464
|
-
}
|
|
465
|
-
function appendInjection(bgl, kind) {
|
|
466
|
-
const start = bgl.length;
|
|
467
|
-
switch (kind) {
|
|
468
|
-
case "ibl":
|
|
469
|
-
return [
|
|
470
|
-
// binding start+0: irradianceMap (texture_cube)
|
|
471
|
-
{
|
|
472
|
-
binding: start,
|
|
473
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
474
|
-
texture: { sampleType: "float", viewDimension: "cube" }
|
|
475
|
-
},
|
|
476
|
-
// binding start+1: irradianceSampler
|
|
477
|
-
{
|
|
478
|
-
binding: start + 1,
|
|
479
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
480
|
-
sampler: { type: "filtering" }
|
|
481
|
-
},
|
|
482
|
-
// binding start+2: prefilterMap (texture_cube)
|
|
483
|
-
{
|
|
484
|
-
binding: start + 2,
|
|
485
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
486
|
-
texture: { sampleType: "float", viewDimension: "cube" }
|
|
487
|
-
},
|
|
488
|
-
// binding start+3: prefilterSampler
|
|
489
|
-
{
|
|
490
|
-
binding: start + 3,
|
|
491
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
492
|
-
sampler: { type: "filtering" }
|
|
493
|
-
},
|
|
494
|
-
// binding start+4: brdfLut (texture_2d)
|
|
495
|
-
{
|
|
496
|
-
binding: start + 4,
|
|
497
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
498
|
-
texture: { sampleType: "float", viewDimension: "2d" }
|
|
499
|
-
},
|
|
500
|
-
// binding start+5: brdfLutSampler
|
|
501
|
-
{
|
|
502
|
-
binding: start + 5,
|
|
503
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
504
|
-
sampler: { type: "filtering" }
|
|
505
|
-
},
|
|
506
|
-
// binding start+6: uniform { intensity: f32 }
|
|
507
|
-
{
|
|
508
|
-
binding: start + 6,
|
|
509
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
510
|
-
buffer: { type: "uniform" }
|
|
511
|
-
}
|
|
512
|
-
];
|
|
513
|
-
case "lightmap":
|
|
514
|
-
return [
|
|
515
|
-
// emissive sampler + texture pair
|
|
516
|
-
{
|
|
517
|
-
binding: start,
|
|
518
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
519
|
-
sampler: { type: "filtering" }
|
|
520
|
-
},
|
|
521
|
-
{
|
|
522
|
-
binding: start + 1,
|
|
523
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
524
|
-
texture: { sampleType: "float", viewDimension: "2d" }
|
|
525
|
-
},
|
|
526
|
-
// occlusion sampler + texture pair
|
|
527
|
-
{
|
|
528
|
-
binding: start + 2,
|
|
529
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
530
|
-
sampler: { type: "filtering" }
|
|
531
|
-
},
|
|
532
|
-
{
|
|
533
|
-
binding: start + 3,
|
|
534
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
535
|
-
texture: { sampleType: "float", viewDimension: "2d" }
|
|
536
|
-
}
|
|
537
|
-
];
|
|
538
|
-
case "shadow":
|
|
539
|
-
return [
|
|
540
|
-
{
|
|
541
|
-
binding: start,
|
|
542
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
543
|
-
sampler: { type: "comparison" }
|
|
544
|
-
},
|
|
545
|
-
{
|
|
546
|
-
binding: start + 1,
|
|
547
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
548
|
-
texture: { sampleType: "depth", viewDimension: "2d" }
|
|
549
|
-
}
|
|
550
|
-
];
|
|
551
|
-
case "transmission":
|
|
552
|
-
return [
|
|
553
|
-
{
|
|
554
|
-
binding: start,
|
|
555
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
556
|
-
sampler: { type: "filtering" }
|
|
557
|
-
},
|
|
558
|
-
{
|
|
559
|
-
binding: start + 1,
|
|
560
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
561
|
-
texture: { sampleType: "float", viewDimension: "2d" }
|
|
562
|
-
}
|
|
563
|
-
];
|
|
564
|
-
}
|
|
565
|
-
}
|
|
566
|
-
function appendSingleLayerMediumInjection(bgl) {
|
|
567
|
-
const start = bgl.length;
|
|
568
|
-
return [
|
|
569
|
-
{
|
|
570
|
-
binding: start,
|
|
571
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
572
|
-
sampler: { type: "non-filtering" }
|
|
573
|
-
},
|
|
574
|
-
{
|
|
575
|
-
binding: start + 1,
|
|
576
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
577
|
-
texture: { sampleType: "unfilterable-float", viewDimension: "2d" }
|
|
578
|
-
},
|
|
579
|
-
{
|
|
580
|
-
binding: start + 2,
|
|
581
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
582
|
-
sampler: { type: "filtering" }
|
|
583
|
-
},
|
|
584
|
-
{
|
|
585
|
-
binding: start + 3,
|
|
586
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
587
|
-
texture: { sampleType: "float", viewDimension: "2d" }
|
|
588
|
-
},
|
|
589
|
-
{
|
|
590
|
-
binding: start + 4,
|
|
591
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
592
|
-
sampler: { type: "non-filtering" }
|
|
593
|
-
},
|
|
594
|
-
{
|
|
595
|
-
binding: start + 5,
|
|
596
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
597
|
-
texture: { sampleType: "unfilterable-float", viewDimension: "2d" }
|
|
598
|
-
}
|
|
599
|
-
];
|
|
600
|
-
}
|
|
601
|
-
function physicalTextureFields(paramSchema) {
|
|
602
|
-
return standardPhysicalTextureFields(paramSchema);
|
|
603
|
-
}
|
|
604
|
-
function appendTextureInjection(_bgl, fields) {
|
|
605
|
-
const fieldSet = new Set(fields);
|
|
606
|
-
return standardPhysicalTextureFields(
|
|
607
|
-
STANDARD_PIPELINE_PARAM_SCHEMA.concat(
|
|
608
|
-
fields.map((name) => ({ name, type: "texture2d" }))
|
|
609
|
-
)
|
|
610
|
-
).flatMap((field) => {
|
|
611
|
-
if (!fieldSet.has(field)) return [];
|
|
612
|
-
const canonicalIndex = STANDARD_PHYSICAL_TEXTURE_FIELDS.indexOf(field);
|
|
613
|
-
const binding = 26 + canonicalIndex * 2;
|
|
614
|
-
return [
|
|
615
|
-
{
|
|
616
|
-
binding,
|
|
617
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
618
|
-
sampler: { type: "filtering" }
|
|
619
|
-
},
|
|
620
|
-
{
|
|
621
|
-
binding: binding + 1,
|
|
622
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
623
|
-
texture: { sampleType: "float", viewDimension: "2d" }
|
|
624
|
-
}
|
|
625
|
-
];
|
|
626
|
-
});
|
|
627
|
-
}
|
|
628
|
-
function materialBindGroupLayoutIdentity(shaderId, paramSchema) {
|
|
629
|
-
const descriptor = buildBindGroupLayoutDescriptor(
|
|
630
|
-
{
|
|
631
|
-
shader: { id: shaderId, passKind: "forward", variantSet: void 0 },
|
|
632
|
-
attachments: { colorFormats: [], depthFormat: void 0, sampleCount: 1 }},
|
|
633
|
-
{ kind: "pbr-material-merged", materialParamSchema: paramSchema }
|
|
634
|
-
);
|
|
635
|
-
return JSON.stringify({
|
|
636
|
-
entries: descriptor.entries,
|
|
637
|
-
physicalTextureFields: physicalTextureFields(paramSchema)
|
|
638
|
-
});
|
|
639
|
-
}
|
|
640
|
-
function buildPbrViewBglEntries(caps) {
|
|
641
|
-
const entries = [
|
|
642
|
-
{
|
|
643
|
-
binding: 0,
|
|
644
|
-
visibility: GPU_SHADER_STAGE_VERTEX | GPU_SHADER_STAGE_FRAGMENT,
|
|
645
|
-
// View captures use the same bind group with a per-face view slot.
|
|
646
|
-
// Keeping this dynamic is also valid for the display slot at offset 0.
|
|
647
|
-
buffer: { type: "uniform", hasDynamicOffset: true }
|
|
648
|
-
},
|
|
649
|
-
{
|
|
650
|
-
binding: 3,
|
|
651
|
-
visibility: GPU_SHADER_STAGE_VERTEX | GPU_SHADER_STAGE_FRAGMENT,
|
|
652
|
-
texture: { sampleType: "depth", viewDimension: "2d" }
|
|
653
|
-
},
|
|
654
|
-
{
|
|
655
|
-
binding: 4,
|
|
656
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
657
|
-
sampler: { type: "comparison" }
|
|
658
|
-
},
|
|
659
|
-
// feat-20260612-point-light-shadows-urp-hdrp Round-2 F-1: point shadow
|
|
660
|
-
// cube_array depth atlas. Bound to either the real ShadowAtlas
|
|
661
|
-
// cube_array view (when point shadows are active) or a 1x1x6 fallback
|
|
662
|
-
// cube_array view cleared to 1.0 (fully lit). Visibility is FRAGMENT
|
|
663
|
-
// only -- the directional binding 3 is VERTEX|FRAGMENT for shadow
|
|
664
|
-
// probe-debug sampling, but the cube atlas has no host-side probe path.
|
|
665
|
-
{
|
|
666
|
-
binding: 5,
|
|
667
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
668
|
-
texture: { sampleType: "depth", viewDimension: "cube-array" }
|
|
669
|
-
},
|
|
670
|
-
// feat-20260612-point-light-shadows-urp-hdrp Round-2 F-1: point shadow
|
|
671
|
-
// params UBO. Carries `array<vec4<f32>, 4>` = 64 B with one lane per
|
|
672
|
-
// shadow-casting point light slot (shadowAtlasLayer in [0, 4)). Each
|
|
673
|
-
// lane stores `(near, far, depthBias, normalBias)` so the fragment-shader
|
|
674
|
-
// depth-ref reconstruction (lighting-punctual.wgsl evalPointShadowed)
|
|
675
|
-
// can avoid sampling DirectLightSlot for the URP path. The shared
|
|
676
|
-
// DirectLightSlot metadata remains the identity owner, so binding 6 is
|
|
677
|
-
// unused on HDRP shaders even though the BGL declares it (charter P4 single SSOT
|
|
678
|
-
// BGL across pipelines; the HDRP variant simply doesn't reference the
|
|
679
|
-
// binding in WGSL, which is allowed).
|
|
680
|
-
{
|
|
681
|
-
binding: 6,
|
|
682
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
683
|
-
buffer: { type: "uniform" }
|
|
684
|
-
},
|
|
685
|
-
// feat-20260613-csm-cascaded-shadow-maps M5 / w28: shadowCasterCascade
|
|
686
|
-
// UBO (16 B). Carries the 0-based cascade index of the shadow pass
|
|
687
|
-
// currently being rasterized so `shadow_caster.wgsl` can index into
|
|
688
|
-
// `view.lightViewProj_X` per cascade. Shifted from binding 5 to
|
|
689
|
-
// binding 7 on 2026-06-13 to make room for point-shadow bindings 5/6
|
|
690
|
-
// (they predate this feat in main; CSM's slot was the optimal-yield
|
|
691
|
-
// give since point-shadow needs FRAGMENT-only and the cascade UBO
|
|
692
|
-
// needs vertex-stage too — keeping cascade higher avoids interleaving
|
|
693
|
-
// visibility flags within the contiguous shadow-binding cluster).
|
|
694
|
-
{
|
|
695
|
-
binding: 7,
|
|
696
|
-
visibility: GPU_SHADER_STAGE_VERTEX | GPU_SHADER_STAGE_FRAGMENT,
|
|
697
|
-
buffer: { type: "uniform" }
|
|
698
|
-
},
|
|
699
|
-
// feat-20260625-spot-light-shadow-mapping M3 / w14 (D-5): spot shadow
|
|
700
|
-
// atlas. A single `texture_depth_2d` holding up to 4 spot shadows in a 2x2
|
|
701
|
-
// tile grid (urp-pipeline.ts spotShadowDepth). FRAGMENT-only — the spot
|
|
702
|
-
// shadow factor is reconstructed at fragment time via perspective-divide in
|
|
703
|
-
// `evalSpotShadowed` (lighting-punctual.wgsl).
|
|
704
|
-
//
|
|
705
|
-
// ALWAYS-ON (no caps gate, unlike the point cube_array atlas at binding 5
|
|
706
|
-
// which rides POINT_SHADOW_AVAILABLE): spot uses `texture_depth_2d` which is
|
|
707
|
-
// compat-safe in every WebGPU profile, so the binding is unconditionally
|
|
708
|
-
// declared. The matching WGSL declaration is `spotShadowMap` at @group(0)
|
|
709
|
-
// binding 8 in common.wgsl (also unconditional) — the two must stay in
|
|
710
|
-
// lock-step or WebGPU validation rejects the bind group at smoke time
|
|
711
|
-
// (memory: BGL shape mismatch is a browser-path-only bug). No binding 9
|
|
712
|
-
// sampler: spot reuses the comparison sampler at binding 4.
|
|
713
|
-
// feat-20260625-spot-light-shadow-mapping M3 / w14 (D-5): spot shadow 2D
|
|
714
|
-
// atlas, the LAST view-BG binding. The per-spot fragment-read perspective
|
|
715
|
-
// lightViewProj matrices that w24 originally declared at a standalone
|
|
716
|
-
// binding 9 uniform buffer were folded into the View UBO (binding 0,
|
|
717
|
-
// `view.spotLightViewProj`) in w25 (scope-amend webkit-fallback): the
|
|
718
|
-
// standalone binding pushed the WebGL2 fallback fragment uniform-buffer
|
|
719
|
-
// count to 12, over GLES 3.0's `max_uniform_buffers_per_shader_stage = 11`,
|
|
720
|
-
// crashing pipeline-layout creation on the compat path (this feat's target).
|
|
721
|
-
{
|
|
722
|
-
binding: 8,
|
|
723
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
724
|
-
texture: { sampleType: "depth", viewDimension: "2d" }
|
|
725
|
-
}
|
|
726
|
-
];
|
|
727
|
-
const extendedLighting = caps.extendedLighting ?? true;
|
|
728
|
-
const lowLimitCloudBindings = extendedLighting === false && caps.projectorAvailable === false;
|
|
729
|
-
if (extendedLighting) {
|
|
730
|
-
entries.push(
|
|
731
|
-
{
|
|
732
|
-
binding: 9,
|
|
733
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
734
|
-
sampler: { type: "filtering" }
|
|
735
|
-
},
|
|
736
|
-
{
|
|
737
|
-
binding: 11,
|
|
738
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
739
|
-
texture: { sampleType: "float", viewDimension: "2d-array" }
|
|
740
|
-
},
|
|
741
|
-
{
|
|
742
|
-
binding: 12,
|
|
743
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
744
|
-
texture: { sampleType: "float", viewDimension: "2d-array" }
|
|
745
|
-
},
|
|
746
|
-
{
|
|
747
|
-
binding: 13,
|
|
748
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
749
|
-
texture: { sampleType: "float", viewDimension: "2d" }
|
|
750
|
-
},
|
|
751
|
-
{
|
|
752
|
-
binding: 14,
|
|
753
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
754
|
-
texture: { sampleType: "float", viewDimension: "2d" }
|
|
755
|
-
},
|
|
756
|
-
{
|
|
757
|
-
binding: 15,
|
|
758
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
759
|
-
buffer: { type: "uniform" }
|
|
760
|
-
}
|
|
761
|
-
);
|
|
762
|
-
} else if (caps.projectorAvailable !== false) {
|
|
763
|
-
entries.push(
|
|
764
|
-
{
|
|
765
|
-
binding: 11,
|
|
766
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
767
|
-
texture: { sampleType: "float", viewDimension: "2d" }
|
|
768
|
-
},
|
|
769
|
-
{
|
|
770
|
-
binding: 12,
|
|
771
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
772
|
-
sampler: { type: "filtering" }
|
|
773
|
-
}
|
|
774
|
-
);
|
|
775
|
-
}
|
|
776
|
-
entries.push({
|
|
777
|
-
binding: 10,
|
|
778
|
-
visibility: GPU_SHADER_STAGE_VERTEX,
|
|
779
|
-
buffer: { type: "uniform", hasDynamicOffset: true }
|
|
780
|
-
});
|
|
781
|
-
if (!lowLimitCloudBindings) {
|
|
782
|
-
entries.push(
|
|
783
|
-
{
|
|
784
|
-
binding: 16,
|
|
785
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
786
|
-
texture: { sampleType: "float", viewDimension: "2d" }
|
|
787
|
-
},
|
|
788
|
-
{
|
|
789
|
-
binding: 17,
|
|
790
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
791
|
-
sampler: { type: "filtering" }
|
|
792
|
-
}
|
|
793
|
-
);
|
|
794
|
-
}
|
|
795
|
-
return entries;
|
|
796
|
-
}
|
|
797
|
-
function buildPbrPipelineLayouts(device, caps) {
|
|
798
|
-
const viewBglRes = device.createBindGroupLayout(
|
|
799
|
-
buildBindGroupLayoutDescriptor(BGL_ONLY_SPEC_STUB, { kind: "pbr-view", caps })
|
|
800
|
-
);
|
|
801
|
-
if (!viewBglRes.ok) throw viewBglRes.error;
|
|
802
|
-
const materialBglRes = device.createBindGroupLayout(
|
|
803
|
-
buildBindGroupLayoutDescriptor(BGL_ONLY_SPEC_STUB, {
|
|
804
|
-
kind: "pbr-material-merged",
|
|
805
|
-
caps
|
|
806
|
-
})
|
|
807
|
-
);
|
|
808
|
-
if (!materialBglRes.ok) throw materialBglRes.error;
|
|
809
|
-
const meshArrayBglRes = device.createBindGroupLayout(
|
|
810
|
-
buildBindGroupLayoutDescriptor(BGL_ONLY_SPEC_STUB, { kind: "pbr-mesh-array", caps })
|
|
811
|
-
);
|
|
812
|
-
if (!meshArrayBglRes.ok) throw meshArrayBglRes.error;
|
|
813
|
-
const instancesBglRes = device.createBindGroupLayout(
|
|
814
|
-
buildBindGroupLayoutDescriptor(BGL_ONLY_SPEC_STUB, {
|
|
815
|
-
kind: "pbr-instances",
|
|
816
|
-
caps: { ...caps, probeBlend: false }
|
|
817
|
-
})
|
|
818
|
-
);
|
|
819
|
-
if (!instancesBglRes.ok) throw instancesBglRes.error;
|
|
820
|
-
const probeInstancesBglRes = caps.storageBuffer ? device.createBindGroupLayout(
|
|
821
|
-
buildBindGroupLayoutDescriptor(BGL_ONLY_SPEC_STUB, {
|
|
822
|
-
kind: "pbr-instances",
|
|
823
|
-
caps: { ...caps, probeBlend: true }
|
|
824
|
-
})
|
|
825
|
-
) : { ok: true, value: instancesBglRes.value };
|
|
826
|
-
if (!probeInstancesBglRes.ok) throw probeInstancesBglRes.error;
|
|
827
|
-
const layouts = [
|
|
828
|
-
viewBglRes.value,
|
|
829
|
-
materialBglRes.value,
|
|
830
|
-
meshArrayBglRes.value,
|
|
831
|
-
instancesBglRes.value
|
|
832
|
-
];
|
|
833
|
-
const pipelineLayoutRes = device.createPipelineLayout({
|
|
834
|
-
label: "pbr-pl",
|
|
835
|
-
bindGroupLayouts: layouts
|
|
836
|
-
});
|
|
837
|
-
if (!pipelineLayoutRes.ok) throw pipelineLayoutRes.error;
|
|
838
|
-
const probeLayouts = [viewBglRes.value, materialBglRes.value, meshArrayBglRes.value, probeInstancesBglRes.value];
|
|
839
|
-
let probePipelineLayout = null;
|
|
840
|
-
if (caps.storageBuffer) {
|
|
841
|
-
const probePipelineLayoutRes = device.createPipelineLayout({
|
|
842
|
-
label: "pbr-probe-pl",
|
|
843
|
-
bindGroupLayouts: probeLayouts
|
|
844
|
-
});
|
|
845
|
-
if (!probePipelineLayoutRes.ok) throw probePipelineLayoutRes.error;
|
|
846
|
-
probePipelineLayout = probePipelineLayoutRes.value;
|
|
847
|
-
}
|
|
848
|
-
return {
|
|
849
|
-
pipelineLayout: pipelineLayoutRes.value,
|
|
850
|
-
viewBgl: viewBglRes.value,
|
|
851
|
-
materialBgl: materialBglRes.value,
|
|
852
|
-
meshArrayBgl: meshArrayBglRes.value,
|
|
853
|
-
instancesBgl: instancesBglRes.value,
|
|
854
|
-
probeInstancesBgl: probeInstancesBglRes.value,
|
|
855
|
-
probePipelineLayout,
|
|
856
|
-
bindGroupLayouts: layouts
|
|
857
|
-
};
|
|
858
|
-
}
|
|
859
|
-
var SKIN_MATERIAL_SHADER_ID = "forgeax::pbr-skin";
|
|
860
|
-
var SHADOW_CASTER_SHADER_ID = "forgeax::default-shadow-caster";
|
|
861
|
-
var AUTHORED_STANDARD_ID_RE = /::(?:standard|pbr-skin)(?:-|$)/;
|
|
862
|
-
function isStandardPbrSkinMaterialShader(shaderId) {
|
|
863
|
-
return shaderId === SKIN_MATERIAL_SHADER_ID || shaderId === "forgeax::default-standard-pbr-skin" || shaderId !== void 0 && /::pbr-skin(?:-|$)/.test(shaderId);
|
|
864
|
-
}
|
|
865
|
-
function shadowCasterVariantSet(storageBuffer, skinned, gpuDrivenSceneIndex = false, alphaMask = false, vertexColorAvailable = false) {
|
|
866
|
-
const skinningDisabled = !skinned;
|
|
867
|
-
const defines = {
|
|
868
|
-
ALPHA_MASK: alphaMask,
|
|
869
|
-
GPU_DRIVEN_SCENE_INDEX_AVAILABLE: gpuDrivenSceneIndex,
|
|
870
|
-
GPU_DRIVEN_SCENE_INDEX_EXPLICIT: false,
|
|
871
|
-
SKINNING_DISABLED: skinningDisabled,
|
|
872
|
-
STORAGE_BUFFER_AVAILABLE: storageBuffer
|
|
873
|
-
};
|
|
874
|
-
if (vertexColorAvailable) defines.VERTEX_COLOR_AVAILABLE = true;
|
|
875
|
-
return Object.entries(defines).sort(([left], [right]) => left < right ? -1 : left > right ? 1 : 0).map(([name, value]) => `${name}=${String(value)}`).join("+");
|
|
876
|
-
}
|
|
877
|
-
function resolvePipelineGroup2Contract(source) {
|
|
878
|
-
const withoutComments = source.replace(/\/\*[\s\S]*?\*\//gu, "").replace(/\/\/.*$/gmu, "");
|
|
879
|
-
const bindings = [
|
|
880
|
-
...withoutComments.matchAll(/@group\s*\(\s*2\s*\)\s*@binding\s*\(\s*(\d+)\s*\)/gu)
|
|
881
|
-
].map((match) => Number(match[1]));
|
|
882
|
-
const hasSkinBindings = bindings.includes(1) || bindings.includes(2);
|
|
883
|
-
const hasClusterBindings = bindings.some((binding) => binding >= 3);
|
|
884
|
-
if (hasSkinBindings && hasClusterBindings) return "skin-cluster";
|
|
885
|
-
if (hasSkinBindings) return "skin";
|
|
886
|
-
if (hasClusterBindings) return "cluster";
|
|
887
|
-
return "mesh";
|
|
888
|
-
}
|
|
889
|
-
function isStandardPbrMaterialShader(shaderId) {
|
|
890
|
-
return shaderId === "forgeax::default-standard-pbr" || shaderId === SKIN_MATERIAL_SHADER_ID || shaderId === "forgeax::default-standard-pbr-skin" || shaderId !== void 0 && AUTHORED_STANDARD_ID_RE.test(shaderId);
|
|
891
|
-
}
|
|
892
|
-
function isCanonicalStandardPbrMaterialShader(shaderId) {
|
|
893
|
-
return shaderId === "forgeax::default-standard-pbr" || shaderId === SKIN_MATERIAL_SHADER_ID || shaderId === "forgeax::default-standard-pbr-skin";
|
|
894
|
-
}
|
|
895
|
-
function buildPbrSkinLayouts(device, caps, pbr) {
|
|
896
|
-
const skinMeshArrayBglRes = device.createBindGroupLayout(
|
|
897
|
-
buildBindGroupLayoutDescriptor(BGL_ONLY_SPEC_STUB, {
|
|
898
|
-
kind: "pbr-skin-mesh-array",
|
|
899
|
-
caps
|
|
900
|
-
})
|
|
901
|
-
);
|
|
902
|
-
if (!skinMeshArrayBglRes.ok) throw skinMeshArrayBglRes.error;
|
|
903
|
-
const layouts = [
|
|
904
|
-
pbr.viewBgl,
|
|
905
|
-
pbr.materialBgl,
|
|
906
|
-
skinMeshArrayBglRes.value,
|
|
907
|
-
pbr.instancesBgl
|
|
908
|
-
];
|
|
909
|
-
const pipelineLayoutRes = device.createPipelineLayout({
|
|
910
|
-
label: "pbr-skin-pl",
|
|
911
|
-
bindGroupLayouts: layouts
|
|
912
|
-
});
|
|
913
|
-
if (!pipelineLayoutRes.ok) throw pipelineLayoutRes.error;
|
|
914
|
-
const probeLayouts = [pbr.viewBgl, pbr.materialBgl, skinMeshArrayBglRes.value, pbr.probeInstancesBgl];
|
|
915
|
-
let probePipelineLayout = null;
|
|
916
|
-
if (caps.storageBuffer) {
|
|
917
|
-
const probePipelineLayoutRes = device.createPipelineLayout({
|
|
918
|
-
label: "pbr-skin-probe-pl",
|
|
919
|
-
bindGroupLayouts: probeLayouts
|
|
920
|
-
});
|
|
921
|
-
if (!probePipelineLayoutRes.ok) throw probePipelineLayoutRes.error;
|
|
922
|
-
probePipelineLayout = probePipelineLayoutRes.value;
|
|
923
|
-
}
|
|
924
|
-
return {
|
|
925
|
-
pipelineLayout: pipelineLayoutRes.value,
|
|
926
|
-
viewBgl: pbr.viewBgl,
|
|
927
|
-
materialBgl: pbr.materialBgl,
|
|
928
|
-
meshArrayBgl: skinMeshArrayBglRes.value,
|
|
929
|
-
instancesBgl: pbr.instancesBgl,
|
|
930
|
-
probeInstancesBgl: pbr.probeInstancesBgl,
|
|
931
|
-
probePipelineLayout,
|
|
932
|
-
bindGroupLayouts: layouts
|
|
933
|
-
};
|
|
934
|
-
}
|
|
935
|
-
function buildGpuDrivenPbrInstancesBindGroupLayout(device, caps) {
|
|
936
|
-
if (!caps.storageBuffer) {
|
|
937
|
-
throw new Error("GPU-driven PBR instances layout requires storage-buffer capability");
|
|
938
|
-
}
|
|
939
|
-
const result = device.createBindGroupLayout(
|
|
940
|
-
buildBindGroupLayoutDescriptor(BGL_ONLY_SPEC_STUB, {
|
|
941
|
-
kind: "pbr-gpu-driven-instances",
|
|
942
|
-
caps
|
|
943
|
-
})
|
|
944
|
-
);
|
|
945
|
-
if (!result.ok) throw result.error;
|
|
946
|
-
return result.value;
|
|
947
|
-
}
|
|
948
|
-
function buildSurfaceDirectInstancesBindGroupLayout(device, caps) {
|
|
949
|
-
if (!caps.storageBuffer) {
|
|
950
|
-
throw new Error("Direct Surface instances layout requires storage-buffer capability");
|
|
951
|
-
}
|
|
952
|
-
const result = device.createBindGroupLayout(
|
|
953
|
-
buildBindGroupLayoutDescriptor(BGL_ONLY_SPEC_STUB, {
|
|
954
|
-
kind: "pbr-surface-direct-instances",
|
|
955
|
-
caps
|
|
956
|
-
})
|
|
957
|
-
);
|
|
958
|
-
if (!result.ok) throw result.error;
|
|
959
|
-
return result.value;
|
|
960
|
-
}
|
|
961
|
-
function buildGpuDrivenPbrPipelineLayout(device, pbr, gpuDrivenInstancesBgl) {
|
|
962
|
-
const result = device.createPipelineLayout({
|
|
963
|
-
label: "pbr-gpu-driven-pl",
|
|
964
|
-
bindGroupLayouts: [pbr.viewBgl, pbr.materialBgl, pbr.meshArrayBgl, gpuDrivenInstancesBgl]
|
|
965
|
-
});
|
|
966
|
-
if (!result.ok) throw result.error;
|
|
967
|
-
return result.value;
|
|
968
|
-
}
|
|
969
|
-
function buildGpuDrivenPbrSkinPipelineLayout(device, pbrSkin, gpuDrivenInstancesBgl) {
|
|
970
|
-
const result = device.createPipelineLayout({
|
|
971
|
-
label: "pbr-skin-gpu-driven-pl",
|
|
972
|
-
bindGroupLayouts: [
|
|
973
|
-
pbrSkin.viewBgl,
|
|
974
|
-
pbrSkin.materialBgl,
|
|
975
|
-
pbrSkin.meshArrayBgl,
|
|
976
|
-
gpuDrivenInstancesBgl
|
|
977
|
-
]
|
|
978
|
-
});
|
|
979
|
-
if (!result.ok) throw result.error;
|
|
980
|
-
return result.value;
|
|
981
|
-
}
|
|
982
|
-
function createPbrSkinMeshBindGroupEntries(meshBuffer, meshSize, paletteBuffer, paletteWindowBytes) {
|
|
983
|
-
return [
|
|
984
|
-
{
|
|
985
|
-
binding: 0,
|
|
986
|
-
resource: { kind: "buffer", value: { buffer: meshBuffer, offset: 0, size: meshSize } }
|
|
987
|
-
},
|
|
988
|
-
...[1, 2].map((binding) => ({
|
|
989
|
-
binding,
|
|
990
|
-
resource: {
|
|
991
|
-
kind: "buffer",
|
|
992
|
-
value: {
|
|
993
|
-
buffer: paletteBuffer,
|
|
994
|
-
offset: 0,
|
|
995
|
-
size: paletteWindowBytes
|
|
996
|
-
}
|
|
997
|
-
}
|
|
998
|
-
}))
|
|
999
|
-
];
|
|
1000
|
-
}
|
|
1001
|
-
function pbrSkinMeshDynamicOffsets(meshOffset, paletteOffset) {
|
|
1002
|
-
return [meshOffset, paletteOffset, paletteOffset];
|
|
1003
|
-
}
|
|
1004
|
-
var SPRITE_PASS_PER_INSTANCE_REGION_VARIANT_SET = "";
|
|
1005
|
-
function createHdrpBindGroupLayoutDescriptor() {
|
|
1006
|
-
const meshBufType = "read-only-storage";
|
|
1007
|
-
const clusterBufType = "read-only-storage";
|
|
1008
|
-
return {
|
|
1009
|
-
label: "hdrp-unified-bgl-group2",
|
|
1010
|
-
entries: [
|
|
1011
|
-
{
|
|
1012
|
-
binding: 0,
|
|
1013
|
-
// Standard fragment lighting (transmission/refraction and clustered
|
|
1014
|
-
// evaluation) reads the same mesh transform window as the vertex
|
|
1015
|
-
// stage. Keep this visibility in the HDRP descriptor aligned with
|
|
1016
|
-
// the URP mesh-array descriptor; restricting it to vertex makes the
|
|
1017
|
-
// HDRP pipeline invalid when fs_main accesses `meshes[0]`.
|
|
1018
|
-
visibility: GPU_SHADER_STAGE_VERTEX | GPU_SHADER_STAGE_FRAGMENT,
|
|
1019
|
-
buffer: { type: meshBufType, hasDynamicOffset: true }
|
|
1020
|
-
},
|
|
1021
|
-
// Bindings 1 and 2 stay absent for the URP physical isolation gap.
|
|
1022
|
-
{
|
|
1023
|
-
binding: 3,
|
|
1024
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
1025
|
-
buffer: { type: clusterBufType, hasDynamicOffset: false }
|
|
1026
|
-
},
|
|
1027
|
-
{
|
|
1028
|
-
binding: 4,
|
|
1029
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
1030
|
-
buffer: { type: clusterBufType, hasDynamicOffset: false }
|
|
1031
|
-
},
|
|
1032
|
-
{
|
|
1033
|
-
binding: 5,
|
|
1034
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
1035
|
-
buffer: { type: clusterBufType, hasDynamicOffset: false }
|
|
1036
|
-
},
|
|
1037
|
-
{
|
|
1038
|
-
binding: 6,
|
|
1039
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
1040
|
-
buffer: { type: "uniform", hasDynamicOffset: false }
|
|
1041
|
-
},
|
|
1042
|
-
{
|
|
1043
|
-
binding: 7,
|
|
1044
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
1045
|
-
texture: { sampleType: "float", viewDimension: "2d", multisampled: false }
|
|
1046
|
-
},
|
|
1047
|
-
{
|
|
1048
|
-
binding: 8,
|
|
1049
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
1050
|
-
sampler: { type: "filtering" }
|
|
1051
|
-
}
|
|
1052
|
-
]
|
|
1053
|
-
};
|
|
1054
|
-
}
|
|
1055
|
-
function createHdrpSkinBindGroupLayoutDescriptor() {
|
|
1056
|
-
const base = createHdrpBindGroupLayoutDescriptor();
|
|
1057
|
-
const baseEntries = base.entries;
|
|
1058
|
-
if (baseEntries === void 0 || baseEntries[0] === void 0) {
|
|
1059
|
-
throw new Error("HDRP base group(2) layout must declare mesh binding 0");
|
|
1060
|
-
}
|
|
1061
|
-
const paletteType = "read-only-storage";
|
|
1062
|
-
return {
|
|
1063
|
-
label: "hdrp-skin-unified-bgl-group2",
|
|
1064
|
-
entries: [
|
|
1065
|
-
baseEntries[0],
|
|
1066
|
-
{
|
|
1067
|
-
binding: 1,
|
|
1068
|
-
visibility: GPU_SHADER_STAGE_VERTEX,
|
|
1069
|
-
buffer: { type: paletteType, hasDynamicOffset: true }
|
|
1070
|
-
},
|
|
1071
|
-
{
|
|
1072
|
-
binding: 2,
|
|
1073
|
-
visibility: GPU_SHADER_STAGE_VERTEX,
|
|
1074
|
-
buffer: { type: paletteType, hasDynamicOffset: true }
|
|
1075
|
-
},
|
|
1076
|
-
...baseEntries.slice(1)
|
|
1077
|
-
]
|
|
1078
|
-
};
|
|
1079
|
-
}
|
|
1080
|
-
function resolveMaterialParamSchema(spec, options) {
|
|
1081
|
-
if (options.materialParamSchema !== void 0) return options.materialParamSchema;
|
|
1082
|
-
if (options.registry !== void 0) {
|
|
1083
|
-
const lookup = options.registry.findMaterialArtifact(spec.shader.id);
|
|
1084
|
-
if (lookup.ok) return lookup.value.paramSchema;
|
|
1085
|
-
}
|
|
1086
|
-
return void 0;
|
|
1087
|
-
}
|
|
1088
|
-
function buildBindGroupLayoutDescriptor(spec, options) {
|
|
1089
|
-
switch (options.kind) {
|
|
1090
|
-
case "pbr-view": {
|
|
1091
|
-
const caps = options.caps ?? { };
|
|
1092
|
-
return {
|
|
1093
|
-
label: "pbr-view-bgl",
|
|
1094
|
-
entries: buildPbrViewBglEntries(caps)
|
|
1095
|
-
};
|
|
1096
|
-
}
|
|
1097
|
-
case "pbr-mesh-array": {
|
|
1098
|
-
const caps = options.caps ?? { storageBuffer: true };
|
|
1099
|
-
const meshBufType = caps.storageBuffer ? "read-only-storage" : "uniform";
|
|
1100
|
-
return {
|
|
1101
|
-
label: "pbr-mesh-array-bgl",
|
|
1102
|
-
entries: [
|
|
1103
|
-
{
|
|
1104
|
-
binding: 0,
|
|
1105
|
-
visibility: GPU_SHADER_STAGE_VERTEX | GPU_SHADER_STAGE_FRAGMENT,
|
|
1106
|
-
buffer: { type: meshBufType, hasDynamicOffset: true }
|
|
1107
|
-
}
|
|
1108
|
-
]
|
|
1109
|
-
};
|
|
1110
|
-
}
|
|
1111
|
-
case "pbr-instances": {
|
|
1112
|
-
const caps = options.caps ?? { storageBuffer: true };
|
|
1113
|
-
const meshBufType = caps.storageBuffer ? "read-only-storage" : "uniform";
|
|
1114
|
-
const entries = [
|
|
1115
|
-
{
|
|
1116
|
-
binding: 0,
|
|
1117
|
-
visibility: GPU_SHADER_STAGE_VERTEX,
|
|
1118
|
-
buffer: { type: meshBufType, hasDynamicOffset: false }
|
|
1119
|
-
},
|
|
1120
|
-
...caps.probeBlend === true ? [
|
|
1121
|
-
{
|
|
1122
|
-
// Per-object fragment lane; the record is always exactly 160B.
|
|
1123
|
-
binding: 1,
|
|
1124
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
1125
|
-
buffer: { type: meshBufType, hasDynamicOffset: true }
|
|
1126
|
-
}
|
|
1127
|
-
] : []
|
|
1128
|
-
];
|
|
1129
|
-
return {
|
|
1130
|
-
label: caps.probeBlend === true ? "pbr-probe-instances-bgl" : "pbr-instances-bgl",
|
|
1131
|
-
entries: entries.map(
|
|
1132
|
-
(entry) => entry.binding === 0 ? {
|
|
1133
|
-
...entry,
|
|
1134
|
-
// Standard transmission reads the same per-instance transform in
|
|
1135
|
-
// fs_main to convert glTF unit-space thickness into world metres.
|
|
1136
|
-
visibility: GPU_SHADER_STAGE_VERTEX | GPU_SHADER_STAGE_FRAGMENT
|
|
1137
|
-
} : entry
|
|
1138
|
-
)
|
|
1139
|
-
};
|
|
1140
|
-
}
|
|
1141
|
-
case "pbr-gpu-driven-instances": {
|
|
1142
|
-
const caps = options.caps ?? { storageBuffer: true };
|
|
1143
|
-
const meshBufType = caps.storageBuffer ? "read-only-storage" : "uniform";
|
|
1144
|
-
return {
|
|
1145
|
-
label: "pbr-gpu-driven-instances-bgl",
|
|
1146
|
-
entries: [
|
|
1147
|
-
{
|
|
1148
|
-
binding: 0,
|
|
1149
|
-
visibility: GPU_SHADER_STAGE_VERTEX,
|
|
1150
|
-
buffer: { type: meshBufType, hasDynamicOffset: false }
|
|
1151
|
-
},
|
|
1152
|
-
{
|
|
1153
|
-
// ShadowCaster's scene-index entry still reads the visible row
|
|
1154
|
-
// through binding(1). Keep this alias in the dedicated layout so
|
|
1155
|
-
// the shared visible bind group can serve both the Standard PBR
|
|
1156
|
-
// (binding(2)) and depth-only shadow (binding(1)) consumers.
|
|
1157
|
-
binding: 1,
|
|
1158
|
-
visibility: GPU_SHADER_STAGE_VERTEX | GPU_SHADER_STAGE_FRAGMENT,
|
|
1159
|
-
buffer: { type: meshBufType, hasDynamicOffset: false }
|
|
1160
|
-
},
|
|
1161
|
-
{
|
|
1162
|
-
binding: 2,
|
|
1163
|
-
visibility: GPU_SHADER_STAGE_VERTEX,
|
|
1164
|
-
buffer: { type: meshBufType, hasDynamicOffset: false }
|
|
1165
|
-
},
|
|
1166
|
-
{
|
|
1167
|
-
// Generic Surface dynamic pages are read by authored Surface
|
|
1168
|
-
// accessors. The binding is present for every scene-index group
|
|
1169
|
-
// so Standard and custom Surface batches share one owner shape.
|
|
1170
|
-
binding: 3,
|
|
1171
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
1172
|
-
buffer: { type: meshBufType, hasDynamicOffset: false }
|
|
1173
|
-
},
|
|
1174
|
-
{
|
|
1175
|
-
// Frame time, explicit event ranges, and paired background/depth
|
|
1176
|
-
// facts use separate read-only pages. This keeps live state out
|
|
1177
|
-
// of the material row and leaves skin's address lane untouched.
|
|
1178
|
-
binding: 4,
|
|
1179
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
1180
|
-
buffer: { type: meshBufType, hasDynamicOffset: false }
|
|
1181
|
-
},
|
|
1182
|
-
{
|
|
1183
|
-
// Frame time is one frame-global fact. Keeping it outside the
|
|
1184
|
-
// member row prevents a stable frame from issuing one 4-byte
|
|
1185
|
-
// queue write for every visible Surface member.
|
|
1186
|
-
binding: 5,
|
|
1187
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
1188
|
-
buffer: { type: "uniform", hasDynamicOffset: false }
|
|
1189
|
-
}
|
|
1190
|
-
]
|
|
1191
|
-
};
|
|
1192
|
-
}
|
|
1193
|
-
case "pbr-surface-direct-instances": {
|
|
1194
|
-
return {
|
|
1195
|
-
label: "pbr-surface-direct-instances-bgl",
|
|
1196
|
-
entries: [
|
|
1197
|
-
{
|
|
1198
|
-
binding: 0,
|
|
1199
|
-
// Direct instance transforms are consumed only by vs_main. Keep
|
|
1200
|
-
// them out of the fragment-stage storage budget; Surface already
|
|
1201
|
-
// needs the retained ProbeBlend/page/frame records there and the
|
|
1202
|
-
// portable WebGPU limit is eight storage buffers per stage.
|
|
1203
|
-
visibility: GPU_SHADER_STAGE_VERTEX,
|
|
1204
|
-
buffer: { type: "read-only-storage", hasDynamicOffset: false }
|
|
1205
|
-
},
|
|
1206
|
-
{
|
|
1207
|
-
binding: 1,
|
|
1208
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
1209
|
-
buffer: { type: "read-only-storage", hasDynamicOffset: true }
|
|
1210
|
-
},
|
|
1211
|
-
{
|
|
1212
|
-
binding: 3,
|
|
1213
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
1214
|
-
buffer: { type: "read-only-storage", hasDynamicOffset: false }
|
|
1215
|
-
},
|
|
1216
|
-
{
|
|
1217
|
-
binding: 4,
|
|
1218
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
1219
|
-
buffer: { type: "read-only-storage", hasDynamicOffset: false }
|
|
1220
|
-
},
|
|
1221
|
-
{
|
|
1222
|
-
binding: 5,
|
|
1223
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
1224
|
-
buffer: { type: "uniform", hasDynamicOffset: false }
|
|
1225
|
-
},
|
|
1226
|
-
{
|
|
1227
|
-
binding: 6,
|
|
1228
|
-
visibility: GPU_SHADER_STAGE_VERTEX,
|
|
1229
|
-
buffer: { type: "uniform", hasDynamicOffset: false }
|
|
1230
|
-
}
|
|
1231
|
-
]
|
|
1232
|
-
};
|
|
1233
|
-
}
|
|
1234
|
-
case "pbr-skin-mesh-array": {
|
|
1235
|
-
const caps = options.caps ?? { storageBuffer: true };
|
|
1236
|
-
const meshBufType = caps.storageBuffer ? "read-only-storage" : "uniform";
|
|
1237
|
-
return {
|
|
1238
|
-
label: "pbr-skin-mesh-array-bgl",
|
|
1239
|
-
entries: [
|
|
1240
|
-
{
|
|
1241
|
-
binding: 0,
|
|
1242
|
-
visibility: GPU_SHADER_STAGE_VERTEX | GPU_SHADER_STAGE_FRAGMENT,
|
|
1243
|
-
buffer: { type: meshBufType, hasDynamicOffset: true }
|
|
1244
|
-
},
|
|
1245
|
-
{
|
|
1246
|
-
binding: 1,
|
|
1247
|
-
visibility: GPU_SHADER_STAGE_VERTEX,
|
|
1248
|
-
buffer: { type: meshBufType, hasDynamicOffset: true }
|
|
1249
|
-
},
|
|
1250
|
-
{
|
|
1251
|
-
binding: 2,
|
|
1252
|
-
visibility: GPU_SHADER_STAGE_VERTEX,
|
|
1253
|
-
buffer: { type: meshBufType, hasDynamicOffset: true }
|
|
1254
|
-
}
|
|
1255
|
-
]
|
|
1256
|
-
};
|
|
1257
|
-
}
|
|
1258
|
-
case "pbr-material-merged": {
|
|
1259
|
-
const resolvedSchema = resolveMaterialParamSchema(spec, options);
|
|
1260
|
-
const effectiveSchema = resolvedSchema ?? STANDARD_PIPELINE_PARAM_SCHEMA;
|
|
1261
|
-
const physicalFields = physicalTextureFields(effectiveSchema);
|
|
1262
|
-
const userRegionSchema = isCanonicalStandardPbrMaterialShader(spec.shader.id) ? STANDARD_PIPELINE_PARAM_SCHEMA : effectiveSchema;
|
|
1263
|
-
const userRegion = buildPbrMaterialUserRegionEntries(userRegionSchema);
|
|
1264
|
-
const afterIbl = [...userRegion, ...appendInjection(userRegion, "ibl")];
|
|
1265
|
-
const afterTransmission = [...afterIbl, ...appendInjection(afterIbl, "transmission")];
|
|
1266
|
-
const engineRegion = options.caps?.transmissionBackdrop === false && spec.shader.id !== "forgeax::single-layer-medium" ? afterIbl : afterTransmission;
|
|
1267
|
-
const afterSurfaceMedium = spec.shader.id === "forgeax::single-layer-medium" ? [...engineRegion, ...appendSingleLayerMediumInjection(engineRegion)] : engineRegion;
|
|
1268
|
-
const merged = [
|
|
1269
|
-
...afterSurfaceMedium,
|
|
1270
|
-
...appendTextureInjection(afterSurfaceMedium, physicalFields)
|
|
1271
|
-
];
|
|
1272
|
-
if (options.caps?.storageBuffer ?? true) {
|
|
1273
|
-
merged.push({
|
|
1274
|
-
binding: 46,
|
|
1275
|
-
visibility: GPU_SHADER_STAGE_VERTEX | GPU_SHADER_STAGE_FRAGMENT,
|
|
1276
|
-
buffer: { type: "read-only-storage", hasDynamicOffset: false }
|
|
1277
|
-
});
|
|
1278
|
-
}
|
|
1279
|
-
const entries = [
|
|
1280
|
-
...merged,
|
|
1281
|
-
...spec.shader.id === "forgeax::single-layer-medium" ? [] : [
|
|
1282
|
-
{
|
|
1283
|
-
binding: 47,
|
|
1284
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
1285
|
-
texture: { sampleType: "float", viewDimension: "cube" }
|
|
1286
|
-
}
|
|
1287
|
-
]
|
|
1288
|
-
];
|
|
1289
|
-
return {
|
|
1290
|
-
label: "pbr-material-skylight-bgl",
|
|
1291
|
-
entries
|
|
1292
|
-
};
|
|
1293
|
-
}
|
|
1294
|
-
case "unlit-material": {
|
|
1295
|
-
const resolvedSchema = resolveMaterialParamSchema(spec, options);
|
|
1296
|
-
return {
|
|
1297
|
-
label: "unlit-material-bgl",
|
|
1298
|
-
entries: buildPbrMaterialUserRegionEntries(resolvedSchema)
|
|
1299
|
-
};
|
|
1300
|
-
}
|
|
1301
|
-
case "hdrp-7-slot": {
|
|
1302
|
-
const desc = createHdrpBindGroupLayoutDescriptor();
|
|
1303
|
-
return {
|
|
1304
|
-
label: desc.label ?? "hdrp-unified-bgl-group2",
|
|
1305
|
-
entries: [...desc.entries ?? []]
|
|
1306
|
-
};
|
|
1307
|
-
}
|
|
1308
|
-
case "fullscreen-post": {
|
|
1309
|
-
return {
|
|
1310
|
-
label: "fullscreen-post-bgl",
|
|
1311
|
-
entries: buildFullscreenPostInputEntries(spec)
|
|
1312
|
-
};
|
|
1313
|
-
}
|
|
1314
|
-
case "fullscreen-post-with-params": {
|
|
1315
|
-
return {
|
|
1316
|
-
label: "fullscreen-post-with-params-bgl",
|
|
1317
|
-
entries: [
|
|
1318
|
-
...buildFullscreenPostInputEntries(spec),
|
|
1319
|
-
{
|
|
1320
|
-
binding: 2,
|
|
1321
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
1322
|
-
buffer: { type: "uniform" }
|
|
1323
|
-
}
|
|
1324
|
-
]
|
|
1325
|
-
};
|
|
1326
|
-
}
|
|
1327
|
-
case "fullscreen-post-with-scene-depth": {
|
|
1328
|
-
return {
|
|
1329
|
-
label: "fullscreen-post-with-scene-depth-bgl",
|
|
1330
|
-
entries: [
|
|
1331
|
-
...buildFullscreenPostInputEntries(spec),
|
|
1332
|
-
{
|
|
1333
|
-
binding: 2,
|
|
1334
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
1335
|
-
buffer: { type: "uniform" }
|
|
1336
|
-
},
|
|
1337
|
-
{
|
|
1338
|
-
binding: 3,
|
|
1339
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
1340
|
-
texture: { sampleType: "depth", viewDimension: "2d" }
|
|
1341
|
-
},
|
|
1342
|
-
{
|
|
1343
|
-
binding: 4,
|
|
1344
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
1345
|
-
sampler: { type: "non-filtering" }
|
|
1346
|
-
}
|
|
1347
|
-
]
|
|
1348
|
-
};
|
|
1349
|
-
}
|
|
1350
|
-
case "fullscreen-post-with-scene-depth-msaa": {
|
|
1351
|
-
return {
|
|
1352
|
-
label: "fullscreen-post-with-scene-depth-msaa-bgl",
|
|
1353
|
-
entries: [
|
|
1354
|
-
...buildFullscreenPostInputEntries(spec),
|
|
1355
|
-
{
|
|
1356
|
-
binding: 2,
|
|
1357
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
1358
|
-
buffer: { type: "uniform" }
|
|
1359
|
-
},
|
|
1360
|
-
{
|
|
1361
|
-
binding: 3,
|
|
1362
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
1363
|
-
texture: { sampleType: "depth", viewDimension: "2d", multisampled: true }
|
|
1364
|
-
},
|
|
1365
|
-
{
|
|
1366
|
-
binding: 4,
|
|
1367
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
1368
|
-
sampler: { type: "non-filtering" }
|
|
1369
|
-
}
|
|
1370
|
-
]
|
|
1371
|
-
};
|
|
1372
|
-
}
|
|
1373
|
-
case "fullscreen-post-with-paired-msaa": {
|
|
1374
|
-
return {
|
|
1375
|
-
label: "fullscreen-post-with-paired-msaa-bgl",
|
|
1376
|
-
entries: [
|
|
1377
|
-
{
|
|
1378
|
-
binding: 0,
|
|
1379
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
1380
|
-
texture: {
|
|
1381
|
-
sampleType: "unfilterable-float",
|
|
1382
|
-
viewDimension: "2d",
|
|
1383
|
-
multisampled: true
|
|
1384
|
-
}
|
|
1385
|
-
},
|
|
1386
|
-
{
|
|
1387
|
-
binding: 1,
|
|
1388
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
1389
|
-
sampler: { type: "filtering" }
|
|
1390
|
-
},
|
|
1391
|
-
{
|
|
1392
|
-
binding: 2,
|
|
1393
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
1394
|
-
buffer: { type: "uniform" }
|
|
1395
|
-
},
|
|
1396
|
-
{
|
|
1397
|
-
binding: 3,
|
|
1398
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
1399
|
-
texture: { sampleType: "depth", viewDimension: "2d", multisampled: true }
|
|
1400
|
-
},
|
|
1401
|
-
{
|
|
1402
|
-
binding: 4,
|
|
1403
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
1404
|
-
sampler: { type: "non-filtering" }
|
|
1405
|
-
}
|
|
1406
|
-
]
|
|
1407
|
-
};
|
|
1408
|
-
}
|
|
1409
|
-
}
|
|
1410
|
-
}
|
|
1411
|
-
function buildFullscreenPostInputEntries(spec) {
|
|
1412
|
-
const inputFormat = spec.attachments.depthFormat ?? spec.attachments.colorFormats[0];
|
|
1413
|
-
const sampleType = inputFormat === "depth32float" || inputFormat === "depth24plus" || inputFormat === "depth24plus-stencil8" || inputFormat === "depth16unorm" ? "depth" : inputFormat === "r32float" ? "unfilterable-float" : "float";
|
|
1414
|
-
return [
|
|
1415
|
-
{
|
|
1416
|
-
binding: 0,
|
|
1417
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
1418
|
-
texture: { sampleType, viewDimension: "2d" }
|
|
1419
|
-
},
|
|
1420
|
-
{
|
|
1421
|
-
binding: 1,
|
|
1422
|
-
visibility: GPU_SHADER_STAGE_FRAGMENT,
|
|
1423
|
-
sampler: {
|
|
1424
|
-
type: sampleType === "depth" ? "comparison" : "filtering"
|
|
1425
|
-
}
|
|
1426
|
-
}
|
|
1427
|
-
];
|
|
1428
|
-
}
|
|
1429
|
-
|
|
1430
|
-
// src/scene/probe-blend-record.ts
|
|
1431
|
-
var PROBE_BLEND_RECORD_BYTE_SIZE = 160;
|
|
1432
|
-
var PROBE_BLEND_RECORD_STRIDE = 256;
|
|
1433
|
-
var PROBE_BLEND_RECORD_CAPACITY = 64;
|
|
1434
|
-
function probeBlendRecordOffset(objectKey) {
|
|
1435
|
-
if (!Number.isInteger(objectKey) || objectKey < 0) {
|
|
1436
|
-
throw new Error("probe blend record requires a non-negative object key");
|
|
1437
|
-
}
|
|
1438
|
-
return (objectKey + 1) * PROBE_BLEND_RECORD_STRIDE;
|
|
1439
|
-
}
|
|
1440
|
-
|
|
1441
|
-
// src/targets/material-source.ts
|
|
1442
|
-
var sourceBindings = /* @__PURE__ */ new WeakMap();
|
|
1443
|
-
function sourceToken() {
|
|
1444
|
-
return Object.freeze({});
|
|
1445
|
-
}
|
|
1446
|
-
function resolveRenderTargetMaterialSource(source) {
|
|
1447
|
-
return sourceBindings.get(source);
|
|
1448
|
-
}
|
|
1449
|
-
function invalid(field, value, expected) {
|
|
1450
|
-
return {
|
|
1451
|
-
ok: false,
|
|
1452
|
-
error: new RenderTargetDescriptorInvalidError({ field, value, expected })
|
|
1453
|
-
};
|
|
1454
|
-
}
|
|
1455
|
-
function createRenderTargetMaterialSource(target, descriptor, options) {
|
|
1456
|
-
if (options.aspect !== "color") return invalid("aspect", options.aspect, "color");
|
|
1457
|
-
if (options.dimension !== descriptor.shape) {
|
|
1458
|
-
return invalid("dimension", options.dimension, `dimension matches ${descriptor.shape}`);
|
|
1459
|
-
}
|
|
1460
|
-
const mipCount = descriptor.mipLevels === 1 ? 1 : Math.floor(Math.log2(Math.max(descriptor.width, descriptor.height))) + 1;
|
|
1461
|
-
if (!Number.isInteger(options.mipLevel) || options.mipLevel < 0 || options.mipLevel >= mipCount) {
|
|
1462
|
-
return invalid("mipLevel", options.mipLevel, `an admitted mip level below ${mipCount}`);
|
|
1463
|
-
}
|
|
1464
|
-
if (!Number.isInteger(options.generation) || options.generation < 0) {
|
|
1465
|
-
return invalid("generation", options.generation, "a non-negative device generation");
|
|
1466
|
-
}
|
|
1467
|
-
const result = {
|
|
1468
|
-
ok: true,
|
|
1469
|
-
value: Object.freeze({
|
|
1470
|
-
source: sourceToken(),
|
|
1471
|
-
target,
|
|
1472
|
-
generation: options.generation,
|
|
1473
|
-
shape: descriptor.shape,
|
|
1474
|
-
format: descriptor.format,
|
|
1475
|
-
view: Object.freeze({
|
|
1476
|
-
dimension: options.dimension,
|
|
1477
|
-
mipLevel: options.mipLevel,
|
|
1478
|
-
resolveRequired: descriptor.sampleCount === 4
|
|
1479
|
-
})
|
|
1480
|
-
})
|
|
1481
|
-
};
|
|
1482
|
-
sourceBindings.set(result.value.source, result.value);
|
|
1483
|
-
return result;
|
|
1484
|
-
}
|
|
1485
|
-
|
|
1486
|
-
// src/systems/pass-selector.ts
|
|
1487
|
-
function matchPass(tags, selector) {
|
|
1488
|
-
if (Object.keys(selector).length === 0) return true;
|
|
1489
|
-
for (const [key, allowedValues] of Object.entries(selector)) {
|
|
1490
|
-
const passValue = tags[key];
|
|
1491
|
-
if (passValue === void 0) return false;
|
|
1492
|
-
if (allowedValues.length === 0) return false;
|
|
1493
|
-
if (!allowedValues.includes(passValue)) return false;
|
|
1494
|
-
}
|
|
1495
|
-
return true;
|
|
1496
|
-
}
|
|
1497
|
-
function selectPasses(passes, selector) {
|
|
1498
|
-
if (Object.keys(selector).length === 0) return passes;
|
|
1499
|
-
return passes.filter(
|
|
1500
|
-
(p) => matchPass(p.renderState?.tags ?? {}, selector)
|
|
1501
|
-
);
|
|
1502
|
-
}
|
|
1503
|
-
|
|
1504
|
-
// src/gpu-driven/prepared-draw.ts
|
|
1505
|
-
function failure(code, detail) {
|
|
1506
|
-
return { ok: false, error: new GpuDrivenPreparationError(code, detail) };
|
|
1507
|
-
}
|
|
1508
|
-
function hasRequiredVertexInputs(expected, actual) {
|
|
1509
|
-
return expected.every(
|
|
1510
|
-
(input) => actual.some(
|
|
1511
|
-
(candidate) => candidate.semantic === input.semantic && candidate.location === input.location && candidate.format === input.format
|
|
1512
|
-
)
|
|
1513
|
-
);
|
|
1514
|
-
}
|
|
1515
|
-
function hasMaterialResources(snapshot, receipt) {
|
|
1516
|
-
if ((snapshot.material.textureSources?.size ?? 0) > 0 || (snapshot.material.videoTextureFields?.size ?? 0) > 0) {
|
|
1517
|
-
return false;
|
|
1518
|
-
}
|
|
1519
|
-
const textures = snapshot.material.textureHandles;
|
|
1520
|
-
const samplers = snapshot.material.samplerHandles;
|
|
1521
|
-
const authoredTextures = snapshot.material.authoredTextureFields;
|
|
1522
|
-
const authoredSamplers = snapshot.material.authoredSamplerFields;
|
|
1523
|
-
return receipt.resourceSlots.every((slot) => {
|
|
1524
|
-
if (slot.kind === "storage-buffer") {
|
|
1525
|
-
return receipt.surface?.dynamicInput?.group === slot.group && receipt.surface.dynamicInput.binding === slot.binding && slot.group === 3 && slot.binding === 3;
|
|
1526
|
-
}
|
|
1527
|
-
if (slot.kind === "texture") {
|
|
1528
|
-
if (!authoredTextures?.has(slot.parameter)) return true;
|
|
1529
|
-
return textures?.has(slot.parameter) === true || snapshot.material.textureSources?.has(slot.parameter) === true || snapshot.material.videoTextureFields?.has(slot.parameter) === true;
|
|
1530
|
-
}
|
|
1531
|
-
if (!authoredSamplers?.has(slot.parameter)) return true;
|
|
1532
|
-
return samplers?.has(slot.parameter) === true;
|
|
1533
|
-
});
|
|
1534
|
-
}
|
|
1535
|
-
function prepareGpuDrivenDraw(input) {
|
|
1536
|
-
const receipt = input.artifact.receipt;
|
|
1537
|
-
if (receipt === void 0) {
|
|
1538
|
-
return failure("missing-material-receipt", {
|
|
1539
|
-
reason: "material-receipt-missing",
|
|
1540
|
-
owner: "material",
|
|
1541
|
-
expected: "MaterialShaderArtifact.receipt"
|
|
1542
|
-
});
|
|
1543
|
-
}
|
|
1544
|
-
if (receipt.generation !== input.generation) {
|
|
1545
|
-
return failure("stale-generation", {
|
|
1546
|
-
reason: "generation-stale",
|
|
1547
|
-
owner: "generation",
|
|
1548
|
-
expectedGeneration: input.generation,
|
|
1549
|
-
actualGeneration: receipt.generation
|
|
1550
|
-
});
|
|
1551
|
-
}
|
|
1552
|
-
if (receipt.reflection.layoutIdentity !== input.artifact.layoutIdentity) {
|
|
1553
|
-
return failure("reflection-mismatch", {
|
|
1554
|
-
reason: "reflection-receipt-mismatch",
|
|
1555
|
-
owner: "material",
|
|
1556
|
-
expected: input.artifact.layoutIdentity,
|
|
1557
|
-
actual: receipt.reflection.layoutIdentity
|
|
1558
|
-
});
|
|
1559
|
-
}
|
|
1560
|
-
if (receipt.uvSets.some((uv) => uv.set > 0) && input.geometry.vertexInputs.length < 3) {
|
|
1561
|
-
return failure("missing-uv", {
|
|
1562
|
-
reason: "uv-set-missing",
|
|
1563
|
-
owner: "geometry",
|
|
1564
|
-
expected: `${receipt.uvSets.length} material UV sets`,
|
|
1565
|
-
actual: `${input.geometry.vertexInputs.filter((vertex) => vertex.semantic.startsWith("uv")).length} geometry UV sets`
|
|
1566
|
-
});
|
|
1567
|
-
}
|
|
1568
|
-
if (!hasRequiredVertexInputs(receipt.vertexInputs, input.geometry.vertexInputs)) {
|
|
1569
|
-
return failure("vertex-input-mismatch", {
|
|
1570
|
-
reason: "vertex-semantic-mismatch",
|
|
1571
|
-
owner: "geometry",
|
|
1572
|
-
expected: receipt.vertexInputs.map((input2) => input2.semantic).join(","),
|
|
1573
|
-
actual: input.geometry.vertexInputs.map((input2) => input2.semantic).join(",")
|
|
1574
|
-
});
|
|
1575
|
-
}
|
|
1576
|
-
const hasAlphaMask = receipt.alphaMask.cutoff.length > 0 || receipt.alphaMask.source.length > 0;
|
|
1577
|
-
if (hasAlphaMask && (receipt.alphaMask.cutoff.length === 0 || receipt.alphaMask.source.length === 0)) {
|
|
1578
|
-
return failure("alpha-mask-mismatch", {
|
|
1579
|
-
reason: "alpha-mask-receipt-missing",
|
|
1580
|
-
owner: "material",
|
|
1581
|
-
expected: "alphaMask.cutoff and alphaMask.source for a masked Pass"
|
|
1582
|
-
});
|
|
1583
|
-
}
|
|
1584
|
-
if (!hasMaterialResources(input.snapshot, receipt)) {
|
|
1585
|
-
return failure("resource-not-ready", {
|
|
1586
|
-
reason: "material-resource-missing",
|
|
1587
|
-
owner: "material",
|
|
1588
|
-
expected: receipt.resourceSlots.map((slot) => slot.parameter).join(",")
|
|
1589
|
-
});
|
|
1590
|
-
}
|
|
1591
|
-
const deformation = input.snapshot.skin === void 0 ? "rigid" : "skin";
|
|
1592
|
-
if (deformation === "skin") {
|
|
1593
|
-
if (input.skinReceipt === void 0 || receipt.skinPaletteAddress === void 0) {
|
|
1594
|
-
return failure("skin-receipt-mismatch", {
|
|
1595
|
-
reason: "skin-address-missing",
|
|
1596
|
-
owner: "skin",
|
|
1597
|
-
expected: "skinPaletteAddress and skinReceipt"
|
|
1598
|
-
});
|
|
1599
|
-
}
|
|
1600
|
-
if (input.skinReceipt.identity !== input.snapshot.skin?.identity || input.skinReceipt.generation !== input.snapshot.skin?.generation || input.skinReceipt.group !== receipt.skinPaletteAddress.group || input.skinReceipt.binding !== receipt.skinPaletteAddress.binding) {
|
|
1601
|
-
return failure("skin-receipt-mismatch", {
|
|
1602
|
-
reason: "skin-address-missing",
|
|
1603
|
-
owner: "skin",
|
|
1604
|
-
expected: `${receipt.skinPaletteAddress.group}:${receipt.skinPaletteAddress.binding}@${input.snapshot.skin?.generation ?? "<missing>"}`,
|
|
1605
|
-
actual: `${input.skinReceipt.group}:${input.skinReceipt.binding}@${input.skinReceipt.generation}`
|
|
1606
|
-
});
|
|
1607
|
-
}
|
|
1608
|
-
}
|
|
1609
|
-
return {
|
|
1610
|
-
ok: true,
|
|
1611
|
-
value: {
|
|
1612
|
-
identity: {
|
|
1613
|
-
material: input.artifact.material,
|
|
1614
|
-
geometry: input.geometry.identity,
|
|
1615
|
-
deformation
|
|
1616
|
-
},
|
|
1617
|
-
receiptGeneration: receipt.generation,
|
|
1618
|
-
receiptIdentity: receipt.receiptIdentity,
|
|
1619
|
-
directEntry: receipt.directEntry,
|
|
1620
|
-
sceneIndexEntry: receipt.sceneIndexEntry,
|
|
1621
|
-
materialRow: receipt.materialRow,
|
|
1622
|
-
resourceSlots: receipt.resourceSlots,
|
|
1623
|
-
uvSets: receipt.uvSets,
|
|
1624
|
-
vertexInputs: receipt.vertexInputs,
|
|
1625
|
-
alphaMask: receipt.alphaMask,
|
|
1626
|
-
skinPaletteAddress: receipt.skinPaletteAddress,
|
|
1627
|
-
topology: input.draw.topology,
|
|
1628
|
-
indexed: input.draw.kind === "indexed",
|
|
1629
|
-
first: input.draw.first,
|
|
1630
|
-
count: input.draw.count,
|
|
1631
|
-
baseVertex: input.draw.baseVertex
|
|
1632
|
-
}
|
|
1633
|
-
};
|
|
1634
|
-
}
|
|
1635
|
-
|
|
1636
|
-
// src/extract/gpu-driven.ts
|
|
1637
|
-
function gpuDrivenDrawKey(worldEntity, materialHandle, drawItemIndex) {
|
|
1638
|
-
return `${worldEntity}:${materialHandle}:${drawItemIndex}`;
|
|
1639
|
-
}
|
|
1640
|
-
function gpuDrivenShadowDrawKey(worldEntity, materialHandle, drawItemIndex, passIndex) {
|
|
1641
|
-
return `${gpuDrivenDrawKey(worldEntity, materialHandle, drawItemIndex)}:${passIndex}`;
|
|
1642
|
-
}
|
|
1643
|
-
function gpuDrivenMaterialArtifactKey(input) {
|
|
1644
|
-
return [
|
|
1645
|
-
input.material,
|
|
1646
|
-
input.deformation,
|
|
1647
|
-
input.receiptIdentity ?? "<legacy-receipt>",
|
|
1648
|
-
input.receiptGeneration
|
|
1649
|
-
].join("|");
|
|
1650
|
-
}
|
|
1651
|
-
function gpuDrivenSourceDrawItemIndex(draw, compactIndex) {
|
|
1652
|
-
return draw.drawItemIndex ?? compactIndex;
|
|
1653
|
-
}
|
|
1654
|
-
function resolvePreparedGpuDrivenDraw(input) {
|
|
1655
|
-
return prepareGpuDrivenDraw(input);
|
|
1656
|
-
}
|
|
1657
|
-
function gpuDrivenMaterialResourceClass(material) {
|
|
1658
|
-
const textures = [...material.textureHandles?.entries() ?? []].map(([name, handle]) => [name, Number(handle)]).sort(([left], [right]) => left.localeCompare(right));
|
|
1659
|
-
const samplers = [...material.samplerHandles?.entries() ?? []].map(([name, handle]) => [name, Number(handle)]).sort(([left], [right]) => left.localeCompare(right));
|
|
1660
|
-
return JSON.stringify({
|
|
1661
|
-
textures,
|
|
1662
|
-
samplers
|
|
1663
|
-
});
|
|
1664
|
-
}
|
|
1665
|
-
function hasCpuOnlyMaterialResources(material) {
|
|
1666
|
-
return (material.textureSources?.size ?? 0) > 0 || (material.videoTextureFields?.size ?? 0) > 0;
|
|
1667
|
-
}
|
|
1668
|
-
function buildGpuDrivenDraws(input) {
|
|
1669
|
-
const legacy = "submeshes" in input;
|
|
1670
|
-
if (!legacy && input.mesh === void 0) return [];
|
|
1671
|
-
const parsedMesh = legacy ? void 0 : input.mesh;
|
|
1672
|
-
if (!legacy && parsedMesh === void 0) return [];
|
|
1673
|
-
const indexed = legacy ? input.indexed : parsedMesh?.indices !== void 0;
|
|
1674
|
-
const submeshes = legacy ? input.submeshes : parsedMesh?.submeshes ?? [];
|
|
1675
|
-
const layoutProjection = parsedMesh === void 0 ? void 0 : deriveVertexLayoutProjection(parsedMesh.attributes);
|
|
1676
|
-
const geometry = {
|
|
1677
|
-
identity: parsedMesh === void 0 ? "<no-mesh>" : `${parsedMesh.guid ?? "<no-guid>"}:${layoutProjection?.digest ?? ""}`,
|
|
1678
|
-
vertexInputs: (layoutProjection?.attributes ?? []).map((attribute) => ({
|
|
1679
|
-
semantic: attribute.key,
|
|
1680
|
-
location: attribute.shaderLocation,
|
|
1681
|
-
format: attribute.format
|
|
1682
|
-
})),
|
|
1683
|
-
topology: submeshes[0]?.topology ?? "triangle-list",
|
|
1684
|
-
indexed
|
|
1685
|
-
};
|
|
1686
|
-
let nonIndexedFirst = 0;
|
|
1687
|
-
return submeshes.flatMap((submesh, drawItemIndex) => {
|
|
1688
|
-
const drawMaterial = input.materials[submesh.materialSlot] ?? input.fallbackMaterial;
|
|
1689
|
-
const first = indexed ? submesh.indexOffset : nonIndexedFirst;
|
|
1690
|
-
nonIndexedFirst += submesh.vertexCount;
|
|
1691
|
-
if (drawMaterial.transparent === true) return [];
|
|
1692
|
-
const draw = {
|
|
1693
|
-
drawItemIndex,
|
|
1694
|
-
kind: indexed ? "indexed" : "non-indexed",
|
|
1695
|
-
first,
|
|
1696
|
-
count: indexed ? submesh.indexCount : submesh.vertexCount,
|
|
1697
|
-
baseVertex: 0,
|
|
1698
|
-
materialSlot: submesh.materialSlot,
|
|
1699
|
-
topology: submesh.topology,
|
|
1700
|
-
pipelineClass: `${drawMaterial.materialShaderId ?? "forgeax::default-unlit"}|${submesh.topology}|${JSON.stringify(drawMaterial.renderState ?? null)}`,
|
|
1701
|
-
materialResourceClass: gpuDrivenMaterialResourceClass(drawMaterial)
|
|
1702
|
-
};
|
|
1703
|
-
const lodRanges = !legacy ? input.lodMeshes?.map((lodMesh) => {
|
|
1704
|
-
if (lodMesh === void 0) return void 0;
|
|
1705
|
-
const lower = lodMesh.submeshes[drawItemIndex];
|
|
1706
|
-
if (lower === void 0) return void 0;
|
|
1707
|
-
const lowerIndexed = lodMesh.indices !== void 0;
|
|
1708
|
-
const lowerFirst = lowerIndexed ? lower.indexOffset : lodMesh.submeshes.slice(0, drawItemIndex).reduce((offset, entry) => offset + entry.vertexCount, 0);
|
|
1709
|
-
return {
|
|
1710
|
-
first: lowerFirst,
|
|
1711
|
-
count: lowerIndexed ? lower.indexCount : lower.vertexCount,
|
|
1712
|
-
baseVertex: 0
|
|
1713
|
-
};
|
|
1714
|
-
}) : void 0;
|
|
1715
|
-
const withLodRanges = lodRanges?.length !== 0 && lodRanges?.every((range) => range !== void 0) ? { lodRanges } : {};
|
|
1716
|
-
const prepared = legacy ? input.prepare?.(draw, drawMaterial) : hasCpuOnlyMaterialResources(drawMaterial) ? void 0 : (() => {
|
|
1717
|
-
const materialShaderId = drawMaterial.materialShaderId;
|
|
1718
|
-
const vertexColorAvailable = geometry.vertexInputs.some(
|
|
1719
|
-
(input2) => input2.semantic === "color"
|
|
1720
|
-
);
|
|
1721
|
-
const sceneIndexProgramKey = Object.entries(
|
|
1722
|
-
drawMaterial.materialSceneIndexProgramKeys ?? {}
|
|
1723
|
-
).find(
|
|
1724
|
-
([passName, program]) => program.pass === "forward" && drawMaterial.materialProgramKeys?.[passName] === materialShaderId
|
|
1725
|
-
)?.[1]?.specializationKey;
|
|
1726
|
-
const artifact = materialShaderId === void 0 ? void 0 : input.getMaterialShaderArtifact?.(sceneIndexProgramKey ?? materialShaderId, {
|
|
1727
|
-
vertexColorAvailable,
|
|
1728
|
-
deformation: input.baseSnapshot.skin === void 0 ? "rigid" : "skin",
|
|
1729
|
-
pass: "forward",
|
|
1730
|
-
address: "scene-index"
|
|
1731
|
-
});
|
|
1732
|
-
const requiresReceipt = isCanonicalStandardPbrMaterialShader(materialShaderId) || sceneIndexProgramKey !== void 0;
|
|
1733
|
-
if (artifact === void 0) {
|
|
1734
|
-
return input.getMaterialShaderArtifact !== void 0 && requiresReceipt ? new GpuDrivenPreparationError("missing-material-receipt", {
|
|
1735
|
-
reason: "material-receipt-missing",
|
|
1736
|
-
owner: "material",
|
|
1737
|
-
expected: `artifact for ${materialShaderId}`
|
|
1738
|
-
}) : void 0;
|
|
1739
|
-
}
|
|
1740
|
-
const receipt = artifact.receipt;
|
|
1741
|
-
if (receipt === void 0) {
|
|
1742
|
-
return new GpuDrivenPreparationError("missing-material-receipt", {
|
|
1743
|
-
reason: "material-receipt-missing",
|
|
1744
|
-
owner: "material",
|
|
1745
|
-
expected: `receipt for ${materialShaderId}`
|
|
1746
|
-
});
|
|
1747
|
-
}
|
|
1748
|
-
const skinReceipt = input.baseSnapshot.skin !== void 0 && receipt.skinPaletteAddress !== void 0 ? {
|
|
1749
|
-
identity: input.baseSnapshot.skin.identity,
|
|
1750
|
-
generation: input.baseSnapshot.skin.generation,
|
|
1751
|
-
group: receipt.skinPaletteAddress.group,
|
|
1752
|
-
binding: receipt.skinPaletteAddress.binding,
|
|
1753
|
-
byteOffset: input.baseSnapshot.skin.byteOffset
|
|
1754
|
-
} : void 0;
|
|
1755
|
-
const selectedArtifact = artifact === void 0 || sceneIndexProgramKey === void 0 || materialShaderId === void 0 ? artifact : {
|
|
1756
|
-
...artifact,
|
|
1757
|
-
material: materialShaderId,
|
|
1758
|
-
specializationKey: sceneIndexProgramKey
|
|
1759
|
-
};
|
|
1760
|
-
const result = resolvePreparedGpuDrivenDraw({
|
|
1761
|
-
snapshot: { ...input.baseSnapshot, material: drawMaterial },
|
|
1762
|
-
artifact: selectedArtifact ?? artifact,
|
|
1763
|
-
geometry: { ...geometry, topology: draw.topology, indexed: draw.kind === "indexed" },
|
|
1764
|
-
generation: receipt.generation,
|
|
1765
|
-
draw,
|
|
1766
|
-
...skinReceipt === void 0 ? {} : { skinReceipt }
|
|
1767
|
-
});
|
|
1768
|
-
return result.ok ? result.value : result.error;
|
|
1769
|
-
})();
|
|
1770
|
-
if (prepared instanceof GpuDrivenPreparationError) {
|
|
1771
|
-
return [{ ...draw, preparationError: prepared, ...withLodRanges }];
|
|
1772
|
-
}
|
|
1773
|
-
return [
|
|
1774
|
-
prepared === void 0 ? { ...draw, ...withLodRanges } : { ...draw, prepared, ...withLodRanges }
|
|
1775
|
-
];
|
|
1776
|
-
});
|
|
1777
|
-
}
|
|
1778
|
-
|
|
1779
|
-
export { COOKIE_MATRIX_BYTES, COOKIE_SLICE_CAPACITY, COOKIE_SLICE_SIZE, DeviceScope, EXTENDED_LIGHTING_REQUIRED_SAMPLED_TEXTURES, EXTENDED_LIGHTING_TOPOLOGY, GPU_BUFFER_USAGE_COPY_DST, GPU_BUFFER_USAGE_COPY_SRC, GPU_BUFFER_USAGE_INDEX, GPU_BUFFER_USAGE_INDIRECT, GPU_BUFFER_USAGE_MAP_READ, GPU_BUFFER_USAGE_QUERY_RESOLVE, GPU_BUFFER_USAGE_STORAGE, GPU_BUFFER_USAGE_UNIFORM, GPU_BUFFER_USAGE_VERTEX, GPU_SHADER_STAGE_COMPUTE, GPU_SHADER_STAGE_FRAGMENT, GPU_SHADER_STAGE_VERTEX, IES_SLICE_CAPACITY, IES_SLICE_HEIGHT, IES_SLICE_WIDTH, LifecycleTransaction, PROBE_BLEND_RECORD_BYTE_SIZE, PROBE_BLEND_RECORD_CAPACITY, PROBE_BLEND_RECORD_STRIDE, SHADOW_CASTER_SHADER_ID, SKIN_MATERIAL_SHADER_ID, SPRITE_PASS_PER_INSTANCE_REGION_VARIANT_SET, buildBindGroupLayoutDescriptor, buildGpuDrivenDraws, buildGpuDrivenPbrInstancesBindGroupLayout, buildGpuDrivenPbrPipelineLayout, buildGpuDrivenPbrSkinPipelineLayout, buildPbrMaterialUserRegionEntries, buildPbrPipelineLayouts, buildPbrSkinLayouts, buildSurfaceDirectInstancesBindGroupLayout, classifySceneDataCoverage, createHdrpBindGroupLayoutDescriptor, createHdrpSkinBindGroupLayoutDescriptor, createPbrSkinMeshBindGroupEntries, createRenderTargetMaterialSource, createTemporalCoverage, deriveExtendedLightingCapability, extendedLightingSampledTextureCapacityAvailable, getOpaqueResourceIdentity, getTextureIdentity, gpuDrivenDrawKey, gpuDrivenMaterialArtifactKey, gpuDrivenShadowDrawKey, gpuDrivenSourceDrawItemIndex, hasRequiredVertexInputs, instanceCollectionCacheKey, isCanonicalStandardPbrMaterialShader, isStandardPbrMaterialShader, isStandardPbrSkinMaterialShader, makeZeroCameraFallbackSnapshot, matchPass, materialBindGroupLayoutIdentity, pbrSkinMeshDynamicOffsets, physicalTextureFields, probeBlendRecordOffset, resolvePipelineGroup2Contract, resolveRenderTargetMaterialSource, scanSceneDataCoverage, selectPasses, shadowCasterVariantSet, validateGraphTargetCaptureReadback, worldEntityKey };
|
|
1780
|
-
//# sourceMappingURL=chunk-SHFUFJ5N.mjs.map
|
|
1781
|
-
//# sourceMappingURL=chunk-SHFUFJ5N.mjs.map
|