@forgeax/engine-render 0.1.29 → 0.1.31
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 +248 -21
- package/dist/assembly/atmosphere-shader-prewarm.d.ts +1 -1
- package/dist/assembly/atmosphere-shader-prewarm.d.ts.map +1 -1
- package/dist/assembly/device-feature-admission.d.ts +4 -3
- package/dist/assembly/device-feature-admission.d.ts.map +1 -1
- package/dist/assembly/dynamic-geometry-host.d.ts +6 -0
- package/dist/assembly/dynamic-geometry-host.d.ts.map +1 -1
- package/dist/assembly/host-contract.d.ts +6 -0
- package/dist/assembly/host-contract.d.ts.map +1 -1
- package/dist/assembly/material/assembly.d.ts +26 -3
- package/dist/assembly/material/assembly.d.ts.map +1 -1
- package/dist/assembly/material/pipeline-helpers.d.ts +24 -0
- package/dist/assembly/material/pipeline-helpers.d.ts.map +1 -0
- package/dist/assembly/material-shader-policy.d.ts.map +1 -1
- package/dist/assembly/recovery/device-loss-fanout.d.ts.map +1 -1
- package/dist/assembly/recovery/recovery-attempt.d.ts +1 -6
- package/dist/assembly/recovery/recovery-attempt.d.ts.map +1 -1
- package/dist/assembly/recovery/renderer-recover.d.ts +1 -0
- package/dist/assembly/recovery/renderer-recover.d.ts.map +1 -1
- package/dist/assembly/renderer-facade.d.ts.map +1 -1
- package/dist/assembly/shader-prewarm-policy.d.ts +1 -1
- package/dist/assembly/shader-prewarm-policy.d.ts.map +1 -1
- package/dist/assembly/webgpu-ready.d.ts +1 -1
- package/dist/assembly/webgpu-ready.d.ts.map +1 -1
- package/dist/assembly/webgpu-renderer.d.ts.map +1 -1
- package/dist/capture/scene-projection.d.ts +41 -0
- package/dist/capture/scene-projection.d.ts.map +1 -0
- package/dist/{chunk-BQVQOQJH.mjs → chunk-7MQ3XBSP.mjs} +20 -14
- package/dist/chunk-7MQ3XBSP.mjs.map +1 -0
- package/dist/{chunk-S4DNKQYQ.mjs → chunk-C3DDSXYK.mjs} +86 -33
- package/dist/chunk-C3DDSXYK.mjs.map +1 -0
- package/dist/{chunk-BTWH7BP4.mjs → chunk-FUUO4UND.mjs} +73 -29
- package/dist/chunk-FUUO4UND.mjs.map +1 -0
- package/dist/{chunk-NRNXBLIJ.mjs → chunk-JRBDO2KB.mjs} +46 -6
- package/dist/chunk-JRBDO2KB.mjs.map +1 -0
- package/dist/{chunk-NICXSHAT.mjs → chunk-MDQJPY3T.mjs} +8 -6
- package/dist/chunk-MDQJPY3T.mjs.map +1 -0
- package/dist/{chunk-JQTSEI3Z.mjs → chunk-NO4WZCAH.mjs} +3 -3
- package/dist/chunk-NO4WZCAH.mjs.map +1 -0
- package/dist/{chunk-FUODTTIA.mjs → chunk-PSEQ6QPH.mjs} +621 -108
- package/dist/chunk-PSEQ6QPH.mjs.map +1 -0
- package/dist/{chunk-33XZFTQU.mjs → chunk-S5UE2T5P.mjs} +48 -6
- package/dist/chunk-S5UE2T5P.mjs.map +1 -0
- package/dist/components/directional-light.d.ts +2 -2
- package/dist/components/dynamic-resolution.d.ts +15 -0
- package/dist/components/dynamic-resolution.d.ts.map +1 -0
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/light-helpers.d.ts.map +1 -1
- package/dist/components/reflection-probe.d.ts +1 -0
- package/dist/components/reflection-probe.d.ts.map +1 -1
- package/dist/components/skylight.d.ts +4 -1
- package/dist/components/skylight.d.ts.map +1 -1
- package/dist/construct-renderer.mjs +2172 -796
- package/dist/construct-renderer.mjs.map +1 -1
- package/dist/device/device-scope.d.ts +2 -0
- package/dist/device/device-scope.d.ts.map +1 -1
- package/dist/device/gpu-residency.d.ts +2 -2
- package/dist/device/gpu-residency.d.ts.map +1 -1
- package/dist/dynamic-geometry.d.ts.map +1 -1
- package/dist/environment/background.d.ts +3 -2
- package/dist/environment/background.d.ts.map +1 -1
- package/dist/environment/ibl.d.ts +11 -0
- package/dist/environment/ibl.d.ts.map +1 -0
- package/dist/environment/storage.d.ts +14 -0
- package/dist/environment/storage.d.ts.map +1 -0
- package/dist/errors/gpu-driven.d.ts +2 -2
- package/dist/errors/gpu-driven.d.ts.map +1 -1
- package/dist/errors/render.d.ts +35 -1
- package/dist/errors/render.d.ts.map +1 -1
- package/dist/extract/camera.d.ts.map +1 -1
- package/dist/extract/contracts.d.ts +7 -0
- package/dist/extract/contracts.d.ts.map +1 -1
- package/dist/extract/gpu-driven.d.ts +18 -1
- package/dist/extract/gpu-driven.d.ts.map +1 -1
- package/dist/gpu-driven/batch-topology.d.ts.map +1 -1
- package/dist/gpu-driven/material-artifacts.d.ts +24 -0
- package/dist/gpu-driven/material-artifacts.d.ts.map +1 -0
- package/dist/gpu-driven/material-bindings.d.ts +7 -0
- package/dist/gpu-driven/material-bindings.d.ts.map +1 -0
- package/dist/gpu-driven/prepared-draw.d.ts +2 -0
- package/dist/gpu-driven/prepared-draw.d.ts.map +1 -1
- package/dist/gpu-driven/production-raster.d.ts +27 -6
- package/dist/gpu-driven/production-raster.d.ts.map +1 -1
- package/dist/gpu-resource.d.ts +5 -2
- package/dist/gpu-resource.d.ts.map +1 -1
- package/dist/gpu-scene-schema.d.ts.map +1 -1
- package/dist/gpu-scene.d.ts.map +1 -1
- package/dist/hdrp-buffers.d.ts +3 -0
- package/dist/hdrp-buffers.d.ts.map +1 -1
- package/dist/ibl/IblPipelineCache.d.ts +2 -0
- package/dist/ibl/IblPipelineCache.d.ts.map +1 -1
- package/dist/ibl/skylight-bind-group.d.ts +3 -1
- package/dist/ibl/skylight-bind-group.d.ts.map +1 -1
- package/dist/index.d.ts +83 -81
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +7 -5
- package/dist/index.mjs.map +1 -1
- package/dist/inspection-types.d.ts +16 -1
- package/dist/inspection-types.d.ts.map +1 -1
- package/dist/internal.mjs +6 -6
- package/dist/material-row.d.ts +10 -0
- package/dist/material-row.d.ts.map +1 -1
- package/dist/pbr-pipeline.d.ts +3 -1
- package/dist/pbr-pipeline.d.ts.map +1 -1
- package/dist/pipeline/render-extent.d.ts +51 -0
- package/dist/pipeline/render-extent.d.ts.map +1 -0
- package/dist/pipeline/standard-build-context.d.ts +7 -0
- package/dist/pipeline/standard-build-context.d.ts.map +1 -0
- package/dist/pipeline/standard-forward-lane.d.ts +3 -2
- package/dist/pipeline/standard-forward-lane.d.ts.map +1 -1
- package/dist/pipeline/standard-pipeline.d.ts.map +1 -1
- package/dist/pipeline/standard-post.d.ts +1 -1
- package/dist/pipeline/standard-post.d.ts.map +1 -1
- package/dist/pipeline/standard-profile.d.ts +2 -1
- package/dist/pipeline/standard-profile.d.ts.map +1 -1
- package/dist/pipeline-builder.d.ts +3 -1
- package/dist/pipeline-builder.d.ts.map +1 -1
- package/dist/plugin.d.ts.map +1 -1
- package/dist/post-process-errors.d.ts +9 -2
- package/dist/post-process-errors.d.ts.map +1 -1
- package/dist/prepare/extended-lighting/resources.d.ts +3 -3
- package/dist/record/frame-lighting.d.ts.map +1 -1
- package/dist/record/frame-snapshot.d.ts +3 -8
- package/dist/record/frame-snapshot.d.ts.map +1 -1
- package/dist/record/frame.d.ts +3 -2
- package/dist/record/frame.d.ts.map +1 -1
- package/dist/record/main-pass-geometry.d.ts +7 -2
- package/dist/record/main-pass-geometry.d.ts.map +1 -1
- package/dist/record/main-pass-material.d.ts +6 -3
- package/dist/record/main-pass-material.d.ts.map +1 -1
- package/dist/record/main-pass.d.ts +2 -0
- package/dist/record/main-pass.d.ts.map +1 -1
- package/dist/record/prepared-material-bindings.d.ts.map +1 -1
- package/dist/record/recovery-pipeline.d.ts +9 -1
- package/dist/record/recovery-pipeline.d.ts.map +1 -1
- package/dist/record/render-context.d.ts +34 -3
- 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/typed-frame-graph.d.ts +5 -2
- package/dist/record/typed-frame-graph.d.ts.map +1 -1
- package/dist/recovery/render-system-candidate.d.ts.map +1 -1
- package/dist/reflection/background.d.ts +14 -0
- package/dist/reflection/background.d.ts.map +1 -0
- package/dist/reflection/filter.d.ts.map +1 -1
- package/dist/reflection/projection.d.ts +1 -0
- package/dist/reflection/projection.d.ts.map +1 -1
- package/dist/reflection/record-owner.d.ts +4 -2
- package/dist/reflection/record-owner.d.ts.map +1 -1
- package/dist/render-contract.d.ts +47 -32
- package/dist/render-contract.d.ts.map +1 -1
- package/dist/render-graph-primitives.d.ts.map +1 -1
- package/dist/render-pipeline.d.ts +17 -1
- package/dist/render-pipeline.d.ts.map +1 -1
- package/dist/render-system-extract-tail.d.ts +9 -2
- package/dist/render-system-extract-tail.d.ts.map +1 -1
- package/dist/render-system-extract.d.ts +29 -2
- package/dist/render-system-extract.d.ts.map +1 -1
- package/dist/render-system.d.ts.map +1 -1
- package/dist/scene/render-scene.d.ts +2 -0
- package/dist/scene/render-scene.d.ts.map +1 -1
- package/dist/ssao-config.d.ts +8 -6
- package/dist/ssao-config.d.ts.map +1 -1
- package/dist/ssr/graph.d.ts.map +1 -1
- package/dist/temporal/gpu.d.ts.map +1 -1
- package/dist/temporal/index.mjs +5 -5
- package/dist/temporal/standard-scene-data.d.ts +2 -1
- package/dist/temporal/standard-scene-data.d.ts.map +1 -1
- package/dist/temporal/target-coverage-attachment.d.ts +15 -0
- package/dist/temporal/target-coverage-attachment.d.ts.map +1 -0
- package/dist/temporal/temporal-view.d.ts +6 -2
- package/dist/temporal/temporal-view.d.ts.map +1 -1
- package/dist/temporal/view.d.ts +6 -0
- package/dist/temporal/view.d.ts.map +1 -1
- package/dist/typed-render-graph-primitives.d.ts +6 -0
- package/dist/typed-render-graph-primitives.d.ts.map +1 -1
- package/dist/volume/component.d.ts +1 -0
- package/dist/volume/component.d.ts.map +1 -1
- package/package.json +21 -21
- package/src/__tests__/capture-scene-projection.unit.test.ts +24 -0
- package/src/__tests__/device-feature-admission.unit.test.ts +15 -24
- package/src/__tests__/device-loss-fanout.unit.test.ts +43 -0
- package/src/__tests__/dynamic-geometry-batch.unit.test.ts +157 -0
- package/src/__tests__/dynamic-geometry.unit.test.ts +36 -0
- package/src/__tests__/dynamic-resolution-plugin.integration.test.ts +81 -0
- package/src/__tests__/factory-contract.integration.test.ts +164 -1
- package/src/__tests__/frame-observation.contract.test.ts +21 -0
- package/src/__tests__/gpu-driven-baseline.characterization.test.ts +1 -1
- package/src/__tests__/gpu-driven-batch-topology-pbr.unit.test.ts +20 -1
- package/src/__tests__/gpu-driven-lod-cache.unit.test.ts +0 -3
- package/src/__tests__/gpu-driven-mesh-world-identity.unit.test.ts +0 -3
- package/src/__tests__/gpu-driven-pbr.dawn.test.ts +11 -6
- package/src/__tests__/gpu-driven-production.integration.test.ts +13 -25
- package/src/__tests__/gpu-driven-view.unit.test.ts +1 -0
- package/src/__tests__/gpu-pass-timing-browser-runner.ts +15 -0
- package/src/__tests__/gpu-pass-timing.browser.test.ts +14 -1
- package/src/__tests__/gpu-resource-scope.unit.test.ts +71 -0
- package/src/__tests__/gpu-scene.unit.test.ts +55 -1
- package/src/__tests__/materials-standard-contract.unit.test.ts +5 -1
- package/src/__tests__/mesh-submission-lifetime.unit.test.ts +8 -0
- package/src/__tests__/morph-neutral-admission.unit.test.ts +19 -0
- package/src/__tests__/physical-clearcoat.integration.test.ts +6 -1
- package/src/__tests__/post-process-error-policy-owner.unit.test.ts +6 -5
- package/src/__tests__/prepared-gpu-driven-pbr.integration.test.ts +216 -5
- package/src/__tests__/reflection-fallback-async-publication.unit.test.ts +68 -1
- package/src/__tests__/reflection-probe-authoring.unit.test.ts +12 -10
- package/src/__tests__/reflection-probe-box.dawn.test.ts +71 -0
- package/src/__tests__/reflection-probe-filter.unit.test.ts +9 -0
- package/src/__tests__/reflection-probe-orientation.dawn.test.ts +294 -0
- package/src/__tests__/reflection-probe-record-owner.characterization.unit.test.ts +5 -15
- package/src/__tests__/reflection-probe-updates.unit.test.ts +129 -0
- package/src/__tests__/render-error-code-owner.test-d.ts +3 -0
- package/src/__tests__/render-error-detail-ssot.test-d.ts +5 -1
- package/src/__tests__/render-extent.unit.test.ts +63 -0
- package/src/__tests__/render-scene-projection.unit.test.ts +3 -2
- package/src/__tests__/renderer-factory-material-contract.unit.test.ts +173 -9
- package/src/__tests__/shader-manifest-fixture.ts +6 -0
- package/src/__tests__/skinned-shadow-caster.test.ts +8 -1
- package/src/__tests__/specular-environment-scale.dawn.test.ts +4 -2
- package/src/__tests__/ssao-config.unit.test.ts +7 -0
- package/src/__tests__/ssao-surface.dawn.test.ts +252 -0
- package/src/__tests__/ssr-cube-silhouette.dawn.test.ts +270 -0
- package/src/__tests__/ssr-gpu-dispatch.browser.test.ts +51 -43
- package/src/__tests__/ssr-gpu-dispatch.dawn.test.ts +4 -0
- package/src/__tests__/ssr-gpu-dispatch.ts +10 -5
- package/src/__tests__/ssr-graph-topology.unit.test.ts +2 -2
- package/src/__tests__/ssr-hiz.browser.test.ts +1 -1
- package/src/__tests__/ssr-hiz.dawn.test.ts +1 -1
- package/src/__tests__/ssr-spatial.integration.test.ts +1 -1
- package/src/__tests__/standard-cluster-variant-resolution.unit.test.ts +40 -0
- package/src/__tests__/standard-pbr-artifact-assembly.unit.test.ts +238 -1
- package/src/__tests__/standard-profile-oracle.unit.test.ts +27 -0
- package/src/__tests__/taa-coverage-edge.dawn.test.ts +6 -0
- package/src/__tests__/taa-neighborhood-equivalence.dawn.test.ts +5 -1
- package/src/__tests__/taa-stability-feedback.ts +1 -0
- package/src/__tests__/temporal-reset-matrix.unit.test.ts +2 -2
- package/src/__tests__/temporal-view.unit.test.ts +17 -0
- package/src/__tests__/transmission-prewarm.unit.test.ts +57 -0
- package/src/__tests__/volumetric-fog-stage-readback.dawn.test.ts +62 -13
- package/src/__tests__/volumetric-fog-topology.unit.test.ts +7 -7
- package/src/assembly/atmosphere-shader-prewarm.ts +3 -2
- package/src/assembly/device-feature-admission.ts +9 -4
- package/src/assembly/dynamic-geometry-host.ts +236 -163
- package/src/assembly/host-contract.ts +9 -0
- package/src/assembly/material/assembly.ts +350 -6
- package/src/assembly/material/pipeline-helpers.ts +100 -0
- package/src/assembly/material-shader-policy.ts +39 -18
- package/src/assembly/recovery/device-loss-fanout.ts +5 -0
- package/src/assembly/recovery/recovery-attempt.ts +2 -29
- package/src/assembly/recovery/renderer-recover.ts +6 -9
- package/src/assembly/renderer-facade.ts +22 -1
- package/src/assembly/shader-prewarm-policy.ts +14 -1
- package/src/assembly/webgpu-ready.ts +28 -19
- package/src/assembly/webgpu-renderer.ts +95 -95
- package/src/capture/scene-projection.ts +37 -0
- package/src/components/__tests__/dynamic-resolution-schema.unit.test.ts +65 -0
- package/src/components/__tests__/light-radius.integration.test.ts +59 -0
- package/src/components/directional-light.ts +3 -3
- package/src/components/dynamic-resolution.ts +67 -0
- package/src/components/index.ts +1 -0
- package/src/components/light-helpers.ts +6 -1
- package/src/components/reflection-probe.ts +1 -0
- package/src/components/skylight.ts +4 -1
- package/src/device/device-scope.ts +13 -7
- package/src/device/gpu-residency.ts +11 -11
- package/src/dynamic-geometry.ts +13 -8
- package/src/environment/background.ts +30 -12
- package/src/environment/ibl.ts +211 -0
- package/src/environment/storage.ts +63 -0
- package/src/errors/gpu-driven.ts +10 -3
- package/src/errors/render.ts +64 -0
- package/src/extract/camera.ts +12 -1
- package/src/extract/contracts.ts +10 -0
- package/src/extract/gpu-driven.ts +72 -17
- package/src/gpu-driven/batch-topology.ts +33 -11
- package/src/gpu-driven/material-artifacts.ts +179 -0
- package/src/gpu-driven/material-bindings.ts +41 -0
- package/src/gpu-driven/prepared-draw.ts +13 -2
- package/src/gpu-driven/production-raster.ts +681 -164
- package/src/gpu-resource.ts +21 -2
- package/src/gpu-scene-schema.ts +11 -2
- package/src/gpu-scene.ts +14 -3
- package/src/hdrp-buffers.ts +69 -0
- package/src/ibl/IblPipelineCache.ts +5 -0
- package/src/ibl/skylight-bind-group.ts +27 -17
- package/src/index.ts +92 -81
- package/src/inspection-types.ts +16 -1
- package/src/material-row.ts +60 -11
- package/src/pbr-pipeline.ts +13 -2
- package/src/pipeline/render-extent.ts +111 -0
- package/src/pipeline/standard-build-context.ts +7 -0
- package/src/pipeline/standard-forward-lane.ts +41 -24
- package/src/pipeline/standard-pipeline.ts +47 -18
- package/src/pipeline/standard-post.ts +4 -0
- package/src/pipeline/standard-profile.ts +2 -1
- package/src/pipeline-builder.ts +12 -3
- package/src/plugin.ts +4 -0
- package/src/post-process-errors.ts +26 -18
- package/src/prepare/__tests__/extended-lighting-capability.unit.test.ts +2 -2
- package/src/prepare/extended-lighting/resources.ts +3 -3
- package/src/record/__tests__/main-pass-geometry.unit.test.ts +68 -0
- package/src/record/__tests__/material-bg-cache.unit.test.ts +45 -0
- package/src/record/__tests__/material-slot-plan.unit.test.ts +9 -0
- package/src/record/__tests__/recovery-pipeline.unit.test.ts +47 -1
- package/src/record/__tests__/sprite-material-abi.unit.test.ts +7 -3
- package/src/record/__tests__/temporal-payload.unit.test.ts +2 -0
- package/src/record/frame-lighting.ts +3 -1
- package/src/record/frame-snapshot.ts +13 -11
- package/src/record/frame.ts +150 -74
- package/src/record/main-pass-geometry.ts +60 -9
- package/src/record/main-pass-material.ts +47 -19
- package/src/record/main-pass.ts +63 -4
- package/src/record/prepared-material-bindings.ts +4 -0
- package/src/record/recovery-pipeline.ts +56 -0
- package/src/record/render-context.ts +34 -3
- package/src/record/shadow-pass.ts +187 -50
- package/src/record/typed-frame-graph.ts +60 -3
- package/src/record/view-ubo.ts +1 -1
- package/src/recovery/render-system-candidate.ts +54 -11
- package/src/reflection/background.ts +151 -0
- package/src/reflection/filter.ts +3 -0
- package/src/reflection/projection.ts +16 -6
- package/src/reflection/record-owner.ts +282 -86
- package/src/render-contract.ts +50 -32
- package/src/render-graph-primitives.ts +28 -3
- package/src/render-pipeline.ts +20 -1
- package/src/render-system-extract-tail.ts +23 -3
- package/src/render-system-extract.ts +127 -42
- package/src/render-system.ts +35 -7
- package/src/scene/render-scene.ts +8 -0
- package/src/ssao-config.ts +25 -8
- package/src/ssr/graph.ts +78 -58
- package/src/temporal/gpu.ts +5 -0
- package/src/temporal/standard-scene-data.ts +7 -1
- package/src/temporal/target-coverage-attachment.ts +72 -0
- package/src/temporal/temporal-view.ts +10 -4
- package/src/temporal/view.ts +12 -2
- package/src/transmission/__tests__/standard-transmission.dawn.test.ts +24 -9
- package/src/typed-render-graph-primitives.ts +38 -0
- package/src/volume/component.ts +1 -0
- package/src/volume/passes.ts +3 -3
- package/dist/chunk-33XZFTQU.mjs.map +0 -1
- package/dist/chunk-BQVQOQJH.mjs.map +0 -1
- package/dist/chunk-BTWH7BP4.mjs.map +0 -1
- package/dist/chunk-FUODTTIA.mjs.map +0 -1
- package/dist/chunk-JQTSEI3Z.mjs.map +0 -1
- package/dist/chunk-NICXSHAT.mjs.map +0 -1
- package/dist/chunk-NRNXBLIJ.mjs.map +0 -1
- package/dist/chunk-S4DNKQYQ.mjs.map +0 -1
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createMeshBuilder } from '@forgeax/engine-geometry';
|
|
1
2
|
import type { MeshAsset } from '@forgeax/engine-types';
|
|
2
3
|
import { describe, expect, it } from 'vitest';
|
|
3
4
|
import { createDynamicGeometryLifecycle } from '../dynamic-geometry';
|
|
@@ -15,6 +16,41 @@ const mesh = (): MeshAsset => ({
|
|
|
15
16
|
});
|
|
16
17
|
|
|
17
18
|
describe('standard dynamic geometry lifecycle', () => {
|
|
19
|
+
it('accepts a MeshBuilder interleaved color buffer with four vertices', () => {
|
|
20
|
+
const source = createMeshBuilder({
|
|
21
|
+
attributes: {
|
|
22
|
+
position: new Float32Array([0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0]),
|
|
23
|
+
color: new Float32Array(16).fill(1),
|
|
24
|
+
},
|
|
25
|
+
indices: new Uint16Array([0, 1, 2, 0, 2, 3]),
|
|
26
|
+
})
|
|
27
|
+
.build()
|
|
28
|
+
.unwrap();
|
|
29
|
+
expect(source.vertices.length % 3).not.toBe(0);
|
|
30
|
+
const lifecycle = createDynamicGeometryLifecycle();
|
|
31
|
+
expect(lifecycle.prepare({ world: {}, mesh: source, revision: 1 }, 1).ok).toBe(true);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('validates referenced material slots rather than requiring one slot per submesh', () => {
|
|
35
|
+
const source = mesh();
|
|
36
|
+
const shared = { ...source, submeshes: [...source.submeshes, ...source.submeshes] };
|
|
37
|
+
const lifecycle = createDynamicGeometryLifecycle();
|
|
38
|
+
expect(lifecycle.prepare({ world: {}, mesh: shared, revision: 1 }, 1).ok).toBe(true);
|
|
39
|
+
expect(
|
|
40
|
+
lifecycle.prepare(
|
|
41
|
+
{
|
|
42
|
+
world: {},
|
|
43
|
+
mesh: {
|
|
44
|
+
...source,
|
|
45
|
+
submeshes: source.submeshes.map((submesh) => ({ ...submesh, materialSlot: 2 })),
|
|
46
|
+
},
|
|
47
|
+
revision: 1,
|
|
48
|
+
},
|
|
49
|
+
1,
|
|
50
|
+
).ok,
|
|
51
|
+
).toBe(false);
|
|
52
|
+
});
|
|
53
|
+
|
|
18
54
|
it('copies a MeshAsset and publishes only after a matching frame generation', () => {
|
|
19
55
|
const lifecycle = createDynamicGeometryLifecycle();
|
|
20
56
|
const world = {};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { createWorldContext, World } from '@forgeax/engine-ecs';
|
|
2
|
+
import { scenePlugin, Transform } from '@forgeax/engine-scene';
|
|
3
|
+
import { describe, expect, it } from 'vitest';
|
|
4
|
+
import { extractCameraSnapshots } from '../extract/camera';
|
|
5
|
+
import { ANTIALIAS_NONE, ANTIALIAS_TAA, Camera, DynamicResolution, MotionBlur } from '../index';
|
|
6
|
+
import { renderComponentsPlugin } from '../plugin';
|
|
7
|
+
import { extractFrames } from '../render-system-extract';
|
|
8
|
+
|
|
9
|
+
describe('DynamicResolution render component registration', () => {
|
|
10
|
+
it('uses the existing render plugin for add, remove, and extraction retries', async () => {
|
|
11
|
+
const world = new World();
|
|
12
|
+
const context = await createWorldContext(world, [renderComponentsPlugin(), scenePlugin()]);
|
|
13
|
+
const entries = [...world.components.entries()].map(([name]) => name);
|
|
14
|
+
expect(entries).toContain('DynamicResolution');
|
|
15
|
+
|
|
16
|
+
const entity = world
|
|
17
|
+
.spawn(
|
|
18
|
+
{ component: Transform, data: {} },
|
|
19
|
+
{ component: Camera, data: { antialias: ANTIALIAS_TAA } },
|
|
20
|
+
{ component: DynamicResolution, data: { minScale: 0.5, maxScale: 0.5 } },
|
|
21
|
+
)
|
|
22
|
+
.unwrap();
|
|
23
|
+
world.update(1 / 60).unwrap();
|
|
24
|
+
expect(extractCameraSnapshots(world)[0]?.dynamicResolution).toMatchObject({
|
|
25
|
+
minScale: 0.5,
|
|
26
|
+
maxScale: 0.5,
|
|
27
|
+
});
|
|
28
|
+
expect(extractCameraSnapshots(world)[0]?.dynamicResolution?.targetGpuMs).toBeCloseTo(16.67);
|
|
29
|
+
|
|
30
|
+
world.removeComponent(entity, DynamicResolution).unwrap();
|
|
31
|
+
expect(extractCameraSnapshots(world)[0]?.dynamicResolution).toBeUndefined();
|
|
32
|
+
expect(extractFrames([world], 0).cameras[0]?.dynamicResolution).toBeUndefined();
|
|
33
|
+
world
|
|
34
|
+
.addComponent(entity, {
|
|
35
|
+
component: DynamicResolution,
|
|
36
|
+
data: { minScale: 0.75, maxScale: 0.75 },
|
|
37
|
+
})
|
|
38
|
+
.unwrap();
|
|
39
|
+
expect(extractCameraSnapshots(world)[0]?.dynamicResolution).toMatchObject({
|
|
40
|
+
minScale: 0.75,
|
|
41
|
+
maxScale: 0.75,
|
|
42
|
+
});
|
|
43
|
+
expect(extractCameraSnapshots(world)[0]?.dynamicResolution?.targetGpuMs).toBeCloseTo(16.67);
|
|
44
|
+
|
|
45
|
+
const nonTaa = world.set(entity, Camera, { antialias: ANTIALIAS_NONE });
|
|
46
|
+
expect(nonTaa.ok).toBe(true);
|
|
47
|
+
expect(() => extractCameraSnapshots(world)).toThrowError(
|
|
48
|
+
expect.objectContaining({ code: 'dynamic-resolution-requires-taa' }),
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
await context.fiber.dispose();
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it('registers MotionBlur for the shared camera extraction query', async () => {
|
|
55
|
+
const world = new World();
|
|
56
|
+
const context = await createWorldContext(world, [renderComponentsPlugin(), scenePlugin()]);
|
|
57
|
+
expect([...world.components.entries()].map(([name]) => name)).toContain('MotionBlur');
|
|
58
|
+
|
|
59
|
+
world
|
|
60
|
+
.spawn(
|
|
61
|
+
{ component: Transform, data: {} },
|
|
62
|
+
{ component: Camera, data: { antialias: ANTIALIAS_TAA } },
|
|
63
|
+
{ component: MotionBlur, data: { shutterAngle: 120, maxRadiusPixels: 12, sampleCount: 6 } },
|
|
64
|
+
)
|
|
65
|
+
.unwrap();
|
|
66
|
+
world.update(1 / 60).unwrap();
|
|
67
|
+
|
|
68
|
+
expect(extractCameraSnapshots(world)[0]?.motionBlur).toEqual({
|
|
69
|
+
shutterAngle: 120,
|
|
70
|
+
maxRadiusPixels: 12,
|
|
71
|
+
sampleCount: 6,
|
|
72
|
+
});
|
|
73
|
+
expect(extractFrames([world], 0).cameras[0]?.motionBlur).toEqual({
|
|
74
|
+
shutterAngle: 120,
|
|
75
|
+
maxRadiusPixels: 12,
|
|
76
|
+
sampleCount: 6,
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
await context.fiber.dispose();
|
|
80
|
+
});
|
|
81
|
+
});
|
|
@@ -18,7 +18,15 @@ import { err, ok } from '@forgeax/engine-types';
|
|
|
18
18
|
import { describe, expect, it, vi } from 'vitest';
|
|
19
19
|
import type { RhiBackendPack } from '../assembly/backend-contract';
|
|
20
20
|
import { createRenderer as constructRenderer } from '../assembly/factory';
|
|
21
|
-
import {
|
|
21
|
+
import {
|
|
22
|
+
DirectionalLight,
|
|
23
|
+
DynamicResolution,
|
|
24
|
+
MeshFilter,
|
|
25
|
+
MeshRenderer,
|
|
26
|
+
MotionBlur,
|
|
27
|
+
PointLight,
|
|
28
|
+
SpotLight,
|
|
29
|
+
} from '../components';
|
|
22
30
|
import {
|
|
23
31
|
ANTIALIAS_NONE,
|
|
24
32
|
ANTIALIAS_TAA,
|
|
@@ -931,6 +939,161 @@ describe('factory contract', () => {
|
|
|
931
939
|
expect((await renderer.dispose()).ok).toBe(true);
|
|
932
940
|
});
|
|
933
941
|
|
|
942
|
+
it('rebuilds the TAA graph when DynamicResolution is removed', async () => {
|
|
943
|
+
const renderer = await constructRenderer(
|
|
944
|
+
{ width: 64, height: 64, getContext: () => null },
|
|
945
|
+
{ rhi },
|
|
946
|
+
{ shaderManifestUrl: renderLifecycleManifestUrl() },
|
|
947
|
+
);
|
|
948
|
+
expect((await renderer.initialization).ok).toBe(true);
|
|
949
|
+
const world = new World();
|
|
950
|
+
const attached = renderer.attach(world);
|
|
951
|
+
expect(attached.ok).toBe(true);
|
|
952
|
+
if (!attached.ok) return;
|
|
953
|
+
registerPropagateTransforms(world);
|
|
954
|
+
const camera = world
|
|
955
|
+
.spawn(
|
|
956
|
+
{ component: Transform, data: { pos: [0, 0, 4] } },
|
|
957
|
+
{
|
|
958
|
+
component: LocalCamera,
|
|
959
|
+
data: { fov: 1, aspect: 1, near: 0.1, far: 100, antialias: ANTIALIAS_TAA },
|
|
960
|
+
},
|
|
961
|
+
{
|
|
962
|
+
component: DynamicResolution,
|
|
963
|
+
data: { targetGpuMs: 16.67, minScale: 0.5, maxScale: 0.5 },
|
|
964
|
+
},
|
|
965
|
+
)
|
|
966
|
+
.unwrap();
|
|
967
|
+
const frameInput = () => ({
|
|
968
|
+
leases: [attached.value],
|
|
969
|
+
camera: { lease: attached.value },
|
|
970
|
+
environment: { lease: attached.value },
|
|
971
|
+
});
|
|
972
|
+
expect(world.update().ok).toBe(true);
|
|
973
|
+
expect(renderer.draw(frameInput()).ok).toBe(true);
|
|
974
|
+
const dynamicInspection = renderer.inspect();
|
|
975
|
+
expect(dynamicInspection.perFramePassNames).toContain('standard-scene-coverage');
|
|
976
|
+
expect(dynamicInspection.temporalTarget).toMatchObject({
|
|
977
|
+
descriptor: { width: 32, height: 32 },
|
|
978
|
+
});
|
|
979
|
+
const dynamicGeneration = dynamicInspection.recoveryEvidence.graph.generation;
|
|
980
|
+
|
|
981
|
+
expect(world.removeComponent(camera, DynamicResolution).ok).toBe(true);
|
|
982
|
+
expect(world.update().ok).toBe(true);
|
|
983
|
+
expect(renderer.draw(frameInput()).ok).toBe(true);
|
|
984
|
+
const surfaceInspection = renderer.inspect();
|
|
985
|
+
expect(surfaceInspection.perFramePassNames).not.toContain('standard-scene-coverage');
|
|
986
|
+
expect(surfaceInspection.temporalTarget).toMatchObject({
|
|
987
|
+
descriptor: { width: 64, height: 64 },
|
|
988
|
+
});
|
|
989
|
+
expect(surfaceInspection.recoveryEvidence.graph.generation).toBeGreaterThan(dynamicGeneration);
|
|
990
|
+
await renderer.dispose();
|
|
991
|
+
});
|
|
992
|
+
|
|
993
|
+
it('restores the surface graph after toggling DynamicResolution on and off', async () => {
|
|
994
|
+
const renderer = await constructRenderer(
|
|
995
|
+
{ width: 64, height: 64, getContext: () => null },
|
|
996
|
+
{ rhi },
|
|
997
|
+
{ shaderManifestUrl: renderLifecycleManifestUrl() },
|
|
998
|
+
);
|
|
999
|
+
expect((await renderer.initialization).ok).toBe(true);
|
|
1000
|
+
const world = new World();
|
|
1001
|
+
const attached = renderer.attach(world);
|
|
1002
|
+
expect(attached.ok).toBe(true);
|
|
1003
|
+
if (!attached.ok) return;
|
|
1004
|
+
registerPropagateTransforms(world);
|
|
1005
|
+
const camera = world
|
|
1006
|
+
.spawn(
|
|
1007
|
+
{ component: Transform, data: { pos: [0, 0, 4] } },
|
|
1008
|
+
{
|
|
1009
|
+
component: LocalCamera,
|
|
1010
|
+
data: { fov: 1, aspect: 1, near: 0.1, far: 100, antialias: ANTIALIAS_TAA },
|
|
1011
|
+
},
|
|
1012
|
+
)
|
|
1013
|
+
.unwrap();
|
|
1014
|
+
const frameInput = () => ({
|
|
1015
|
+
leases: [attached.value],
|
|
1016
|
+
camera: { lease: attached.value },
|
|
1017
|
+
environment: { lease: attached.value },
|
|
1018
|
+
});
|
|
1019
|
+
expect(world.update().ok).toBe(true);
|
|
1020
|
+
expect(renderer.draw(frameInput()).ok).toBe(true);
|
|
1021
|
+
expect(renderer.inspect().perFramePassNames).not.toContain('standard-scene-coverage');
|
|
1022
|
+
|
|
1023
|
+
expect(
|
|
1024
|
+
world.addComponent(camera, {
|
|
1025
|
+
component: DynamicResolution,
|
|
1026
|
+
data: { targetGpuMs: 16.67, minScale: 0.5, maxScale: 0.5 },
|
|
1027
|
+
}).ok,
|
|
1028
|
+
).toBe(true);
|
|
1029
|
+
expect(world.update().ok).toBe(true);
|
|
1030
|
+
expect(renderer.draw(frameInput()).ok).toBe(true);
|
|
1031
|
+
const dynamic = renderer.inspect();
|
|
1032
|
+
expect(dynamic.perFramePassNames).toContain('standard-scene-coverage');
|
|
1033
|
+
expect(dynamic.temporalTarget).toMatchObject({ descriptor: { width: 32, height: 32 } });
|
|
1034
|
+
|
|
1035
|
+
expect(world.removeComponent(camera, DynamicResolution).ok).toBe(true);
|
|
1036
|
+
expect(world.update().ok).toBe(true);
|
|
1037
|
+
expect(renderer.draw(frameInput()).ok).toBe(true);
|
|
1038
|
+
const surface = renderer.inspect();
|
|
1039
|
+
expect(surface.perFramePassNames).not.toContain('standard-scene-coverage');
|
|
1040
|
+
expect(surface.temporalTarget).toMatchObject({ descriptor: { width: 64, height: 64 } });
|
|
1041
|
+
await renderer.dispose();
|
|
1042
|
+
});
|
|
1043
|
+
|
|
1044
|
+
it('rebuilds the TAA graph when MotionBlur is added', async () => {
|
|
1045
|
+
const renderer = await constructRenderer(
|
|
1046
|
+
{ width: 64, height: 64, getContext: () => null },
|
|
1047
|
+
{ rhi },
|
|
1048
|
+
{ shaderManifestUrl: renderLifecycleManifestUrl() },
|
|
1049
|
+
);
|
|
1050
|
+
expect((await renderer.initialization).ok).toBe(true);
|
|
1051
|
+
const errors: unknown[] = [];
|
|
1052
|
+
renderer.onError((error) => errors.push(error));
|
|
1053
|
+
const world = new World();
|
|
1054
|
+
const attached = renderer.attach(world);
|
|
1055
|
+
expect(attached.ok).toBe(true);
|
|
1056
|
+
if (!attached.ok) return;
|
|
1057
|
+
registerPropagateTransforms(world);
|
|
1058
|
+
const camera = world
|
|
1059
|
+
.spawn(
|
|
1060
|
+
{ component: Transform, data: { pos: [0, 0, 4] } },
|
|
1061
|
+
{
|
|
1062
|
+
component: LocalCamera,
|
|
1063
|
+
data: { fov: 1, aspect: 1, near: 0.1, far: 100, antialias: ANTIALIAS_TAA },
|
|
1064
|
+
},
|
|
1065
|
+
)
|
|
1066
|
+
.unwrap();
|
|
1067
|
+
const frameInput = () => ({
|
|
1068
|
+
leases: [attached.value],
|
|
1069
|
+
camera: { lease: attached.value },
|
|
1070
|
+
environment: { lease: attached.value },
|
|
1071
|
+
});
|
|
1072
|
+
expect(world.update().ok).toBe(true);
|
|
1073
|
+
expect(renderer.draw(frameInput()).ok).toBe(true);
|
|
1074
|
+
expect(renderer.inspect().perFramePassNames).not.toContain('motion-blur');
|
|
1075
|
+
|
|
1076
|
+
expect(
|
|
1077
|
+
world.addComponent(camera, {
|
|
1078
|
+
component: MotionBlur,
|
|
1079
|
+
data: { shutterAngle: 180, maxRadiusPixels: 8, sampleCount: 4 },
|
|
1080
|
+
}).ok,
|
|
1081
|
+
).toBe(true);
|
|
1082
|
+
expect(world.update().ok).toBe(true);
|
|
1083
|
+
const motionDraw = renderer.draw(frameInput());
|
|
1084
|
+
if (!motionDraw.ok) {
|
|
1085
|
+
throw new Error(JSON.stringify({ error: motionDraw.error, events: errors }));
|
|
1086
|
+
}
|
|
1087
|
+
const inspection = renderer.inspect();
|
|
1088
|
+
expect(inspection.perFramePassNames).toContain('motion-blur');
|
|
1089
|
+
expect(inspection.motionBlur).toMatchObject({
|
|
1090
|
+
enabled: true,
|
|
1091
|
+
status: 'active',
|
|
1092
|
+
temporalDemand: 'scene-data-temporal-v1',
|
|
1093
|
+
});
|
|
1094
|
+
await renderer.dispose();
|
|
1095
|
+
});
|
|
1096
|
+
|
|
934
1097
|
it('retires factory-owned TAA textures and params on an off submit', async () => {
|
|
935
1098
|
const created = new Map<object, string>();
|
|
936
1099
|
const destroyed = new Set<object>();
|
|
@@ -124,4 +124,25 @@ describe('render current-frame observation producer contract', () => {
|
|
|
124
124
|
}),
|
|
125
125
|
).toEqual({ ok: true });
|
|
126
126
|
});
|
|
127
|
+
it('validates every half-float encoding in both word lanes and an unaligned tail', () => {
|
|
128
|
+
const storage = new Uint8Array(8);
|
|
129
|
+
const bytes = storage.subarray(1, 7);
|
|
130
|
+
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
131
|
+
for (let bits = 0; bits <= 0xffff; bits += 1) {
|
|
132
|
+
for (const offset of [0, 2, 4]) {
|
|
133
|
+
bytes.fill(0);
|
|
134
|
+
view.setUint16(offset, bits, true);
|
|
135
|
+
const result = validateGraphTargetCaptureReadback({
|
|
136
|
+
bytes,
|
|
137
|
+
expectedByteLength: bytes.byteLength,
|
|
138
|
+
allowZero: true,
|
|
139
|
+
});
|
|
140
|
+
const finite = (bits & 0x7c00) !== 0x7c00;
|
|
141
|
+
if (result.ok !== finite)
|
|
142
|
+
throw new Error(`half ${bits.toString(16)} at byte ${offset} misclassified`);
|
|
143
|
+
if (!result.ok && result.code !== 'capture-readback-non-finite')
|
|
144
|
+
throw new Error(`half ${bits.toString(16)} returned ${result.code}`);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
});
|
|
127
148
|
});
|
|
@@ -40,7 +40,7 @@ describe('GPU-driven baseline characterization', () => {
|
|
|
40
40
|
it('requires the prepared Standard PBR production owner', () => {
|
|
41
41
|
expect(productionRaster).not.toContain('GPU_DRIVEN_STANDARD_PBR_WGSL');
|
|
42
42
|
expect(productionRaster).not.toContain('class GpuDrivenPbrRaster');
|
|
43
|
-
expect(productionRaster).toContain('
|
|
43
|
+
expect(productionRaster).toContain('MaterialAbiRasterAdapter');
|
|
44
44
|
expect(productionRaster).toContain('preparedPbrCandidateEligible');
|
|
45
45
|
expect(productionRaster).toContain('deriveVertexBufferLayoutFromProjection');
|
|
46
46
|
expect(productionRaster).toContain('vertexLayout.arrayStride');
|
|
@@ -64,6 +64,7 @@ function prepared(overrides: Partial<PreparedGpuDrivenDraw> = {}): PreparedGpuDr
|
|
|
64
64
|
return {
|
|
65
65
|
identity: { material: 'forgeax::default-standard-pbr', geometry: 'cube', deformation: 'rigid' },
|
|
66
66
|
receiptGeneration: receipt.generation,
|
|
67
|
+
receiptIdentity: receipt.receiptIdentity,
|
|
67
68
|
directEntry: receipt.directEntry,
|
|
68
69
|
sceneIndexEntry: receipt.sceneIndexEntry,
|
|
69
70
|
materialRow: receipt.materialRow,
|
|
@@ -218,11 +219,29 @@ describe('PBR prepared GPU-driven batch topology', () => {
|
|
|
218
219
|
expect(plan.candidateCount).toBe(2);
|
|
219
220
|
expect(plan.batches).toHaveLength(2);
|
|
220
221
|
expect(plan.batches[0]?.key).toMatchObject({
|
|
221
|
-
preparedIdentity: 'forgeax::default-standard-pbr|cube|rigid',
|
|
222
|
+
preparedIdentity: 'forgeax::default-standard-pbr|cube|rigid|standard-pbr/material-row-v3',
|
|
222
223
|
resourceIdentity: resourceClass,
|
|
223
224
|
});
|
|
224
225
|
});
|
|
225
226
|
|
|
227
|
+
it('keeps colored and uncolored ABI variants in separate prepared batches', () => {
|
|
228
|
+
const coloredReceipt = createStandardPbrArtifactReceipt(false, true);
|
|
229
|
+
const colored = prepared({
|
|
230
|
+
receiptIdentity: coloredReceipt.receiptIdentity,
|
|
231
|
+
vertexInputs: coloredReceipt.vertexInputs,
|
|
232
|
+
});
|
|
233
|
+
const topology = topologyFor(snapshot(1, prepared()), snapshot(2, colored));
|
|
234
|
+
|
|
235
|
+
expect(topology.plan().candidateCount).toBe(2);
|
|
236
|
+
expect(topology.plan().batches).toHaveLength(2);
|
|
237
|
+
expect(new Set(topology.plan().batches.map((batch) => batch.key.preparedIdentity))).toEqual(
|
|
238
|
+
new Set([
|
|
239
|
+
'forgeax::default-standard-pbr|cube|rigid|standard-pbr/material-row-v3',
|
|
240
|
+
'forgeax::default-standard-pbr|cube|rigid|standard-pbr/material-row-v3/vertex-color',
|
|
241
|
+
]),
|
|
242
|
+
);
|
|
243
|
+
});
|
|
244
|
+
|
|
226
245
|
it('keeps numeric edits in place and patches only resource identity changes', () => {
|
|
227
246
|
const projection = new RenderScene();
|
|
228
247
|
projection.apply([updateSnapshot(snapshot(1, prepared()))]);
|
|
@@ -187,7 +187,6 @@ describe('GPU-driven filtered-plan cache', () => {
|
|
|
187
187
|
meshBySlot: meshes,
|
|
188
188
|
viewBindGroupLayout: viewLayout,
|
|
189
189
|
meshResidencyEpoch: 1,
|
|
190
|
-
hdrp: false,
|
|
191
190
|
})
|
|
192
191
|
.unwrap();
|
|
193
192
|
expect(first).toBeDefined();
|
|
@@ -212,7 +211,6 @@ describe('GPU-driven filtered-plan cache', () => {
|
|
|
212
211
|
meshBySlot: meshes,
|
|
213
212
|
viewBindGroupLayout: viewLayout,
|
|
214
213
|
meshResidencyEpoch: 1,
|
|
215
|
-
hdrp: false,
|
|
216
214
|
})
|
|
217
215
|
.unwrap();
|
|
218
216
|
expect(moved).toBeDefined();
|
|
@@ -243,7 +241,6 @@ describe('GPU-driven filtered-plan cache', () => {
|
|
|
243
241
|
meshBySlot: meshes,
|
|
244
242
|
viewBindGroupLayout: viewLayout,
|
|
245
243
|
meshResidencyEpoch: 1,
|
|
246
|
-
hdrp: false,
|
|
247
244
|
})
|
|
248
245
|
.unwrap();
|
|
249
246
|
|
|
@@ -267,7 +267,6 @@ describe('GPU-driven mesh world identity', () => {
|
|
|
267
267
|
meshBySlot: meshes,
|
|
268
268
|
viewBindGroupLayout: fixture.viewLayout,
|
|
269
269
|
meshResidencyEpoch: 1,
|
|
270
|
-
hdrp: false,
|
|
271
270
|
})
|
|
272
271
|
.unwrap();
|
|
273
272
|
expect(prepared).toBeDefined();
|
|
@@ -310,7 +309,6 @@ describe('GPU-driven mesh world identity', () => {
|
|
|
310
309
|
]),
|
|
311
310
|
viewBindGroupLayout: fixture.viewLayout,
|
|
312
311
|
meshResidencyEpoch: 1,
|
|
313
|
-
hdrp: false,
|
|
314
312
|
})
|
|
315
313
|
.unwrap();
|
|
316
314
|
expect(firstPrepared).toBeDefined();
|
|
@@ -337,7 +335,6 @@ describe('GPU-driven mesh world identity', () => {
|
|
|
337
335
|
]),
|
|
338
336
|
viewBindGroupLayout: fixture.viewLayout,
|
|
339
337
|
meshResidencyEpoch: 1,
|
|
340
|
-
hdrp: false,
|
|
341
338
|
})
|
|
342
339
|
.unwrap();
|
|
343
340
|
expect(secondPrepared).toBeDefined();
|
|
@@ -33,6 +33,7 @@ import {
|
|
|
33
33
|
buildPbrPipelineLayouts,
|
|
34
34
|
} from '../pbr-pipeline';
|
|
35
35
|
import { makeZeroCameraFallbackSnapshot, worldEntityKey } from '../record/frame-snapshot';
|
|
36
|
+
import { MATERIAL_PER_ENTITY_STRIDE } from '../record/render-context';
|
|
36
37
|
import {
|
|
37
38
|
type GpuDrivenShadowBatch,
|
|
38
39
|
type GpuDrivenShadowSubmission,
|
|
@@ -86,7 +87,8 @@ const SHADOW_CASTER_GPU_ALPHA_VARIANT = SHADOW_CASTER_PRODUCER?.variants.find(
|
|
|
86
87
|
defines.SKINNING_DISABLED === true &&
|
|
87
88
|
defines.GPU_DRIVEN_SCENE_INDEX_AVAILABLE === true &&
|
|
88
89
|
defines.GPU_DRIVEN_SCENE_INDEX_EXPLICIT === false &&
|
|
89
|
-
defines.ALPHA_MASK === true
|
|
90
|
+
defines.ALPHA_MASK === true &&
|
|
91
|
+
defines.VERTEX_COLOR_AVAILABLE === false,
|
|
90
92
|
);
|
|
91
93
|
|
|
92
94
|
// The local/native evidence window remains 300 frames. CI already sets the
|
|
@@ -490,13 +492,13 @@ describe('GPU-driven production PBR Dawn regression', () => {
|
|
|
490
492
|
device.queue.writeBuffer(spotCascadeUniform, 16, shadowLightMatrix).unwrap();
|
|
491
493
|
const opaqueMaterialBuffer = device
|
|
492
494
|
.createBuffer({
|
|
493
|
-
size:
|
|
495
|
+
size: MATERIAL_PER_ENTITY_STRIDE,
|
|
494
496
|
usage: GPU_BUFFER_USAGE_UNIFORM | GPU_BUFFER_USAGE_COPY_DST,
|
|
495
497
|
})
|
|
496
498
|
.unwrap();
|
|
497
499
|
const discardedMaterialBuffer = device
|
|
498
500
|
.createBuffer({
|
|
499
|
-
size:
|
|
501
|
+
size: MATERIAL_PER_ENTITY_STRIDE,
|
|
500
502
|
usage: GPU_BUFFER_USAGE_UNIFORM | GPU_BUFFER_USAGE_COPY_DST,
|
|
501
503
|
})
|
|
502
504
|
.unwrap();
|
|
@@ -636,6 +638,7 @@ describe('GPU-driven production PBR Dawn regression', () => {
|
|
|
636
638
|
{ binding: 15, resource: { kind: 'textureView' as const, value: materialCubeView } },
|
|
637
639
|
{ binding: 16, resource: { kind: 'sampler' as const, value: baseColorSampler } },
|
|
638
640
|
{ binding: 17, resource: { kind: 'textureView' as const, value: materialCubeView } },
|
|
641
|
+
{ binding: 47, resource: { kind: 'textureView' as const, value: materialCubeView } },
|
|
639
642
|
{ binding: 18, resource: { kind: 'sampler' as const, value: baseColorSampler } },
|
|
640
643
|
{ binding: 19, resource: { kind: 'textureView' as const, value: baseColorView } },
|
|
641
644
|
{ binding: 20, resource: { kind: 'sampler' as const, value: baseColorSampler } },
|
|
@@ -729,7 +732,7 @@ describe('GPU-driven production PBR Dawn regression', () => {
|
|
|
729
732
|
meshBySlot: new Map(projection.map((slot) => [slot.slot, gpuMesh])),
|
|
730
733
|
viewBindGroupLayout: viewLayout,
|
|
731
734
|
meshResidencyEpoch: 1,
|
|
732
|
-
|
|
735
|
+
|
|
733
736
|
standardPbrArtifact: artifact,
|
|
734
737
|
standardPbrPipelineState: {
|
|
735
738
|
pbrPipelineLayout: pipelineLayout,
|
|
@@ -756,7 +759,9 @@ describe('GPU-driven production PBR Dawn regression', () => {
|
|
|
756
759
|
expect(prepared.value.shadowDrawKeys).toEqual(new Set([shadowKey]));
|
|
757
760
|
expect(prepared.value.standardPbrFrameResources.instancesBindGroup).toBeDefined();
|
|
758
761
|
expect(prepared.value.standardPbrFrameResources.sceneMaterialBuffer).toBe(scene.materialBuffer);
|
|
759
|
-
expect(prepared.value.standardPbrFrameResources.materialStride).toBe(
|
|
762
|
+
expect(prepared.value.standardPbrFrameResources.materialStride).toBe(
|
|
763
|
+
MATERIAL_PER_ENTITY_STRIDE,
|
|
764
|
+
);
|
|
760
765
|
expect(artifact.receipt.alphaMask).toEqual({ cutoff: 'alphaCutoff', source: 'baseColor.a' });
|
|
761
766
|
|
|
762
767
|
const shadowVertexLayout = deriveVertexBufferLayoutFromProjection(gpuMesh.layoutProjection, {
|
|
@@ -885,7 +890,7 @@ describe('GPU-driven production PBR Dawn regression', () => {
|
|
|
885
890
|
meshBindGroup: projection.meshBindGroup,
|
|
886
891
|
visibleBindGroup: projection.visibleBindGroup,
|
|
887
892
|
deformation: projection.deformation,
|
|
888
|
-
|
|
893
|
+
materialGroup: opaqueMaterialBindGroup,
|
|
889
894
|
vertexBuffer: projection.mesh.vertexBuffer.handle,
|
|
890
895
|
...(indexBuffer === null
|
|
891
896
|
? {}
|
|
@@ -281,7 +281,7 @@ describe('GPU-driven production projection', () => {
|
|
|
281
281
|
]),
|
|
282
282
|
viewBindGroupLayout: viewLayout,
|
|
283
283
|
meshResidencyEpoch: 1,
|
|
284
|
-
|
|
284
|
+
|
|
285
285
|
activeEntityKeys: new Set([worldEntityKey(0, 1)]),
|
|
286
286
|
activeEntityRevision: 1,
|
|
287
287
|
})
|
|
@@ -327,7 +327,7 @@ describe('GPU-driven production projection', () => {
|
|
|
327
327
|
]),
|
|
328
328
|
viewBindGroupLayout: viewLayout,
|
|
329
329
|
meshResidencyEpoch: 1,
|
|
330
|
-
|
|
330
|
+
|
|
331
331
|
activeEntityKeys: new Set([worldEntityKey(0, 1)]),
|
|
332
332
|
activeEntityRevision: 1,
|
|
333
333
|
})
|
|
@@ -351,7 +351,7 @@ describe('GPU-driven production projection', () => {
|
|
|
351
351
|
]),
|
|
352
352
|
viewBindGroupLayout: viewLayout,
|
|
353
353
|
meshResidencyEpoch: 1,
|
|
354
|
-
|
|
354
|
+
|
|
355
355
|
activeEntityKeys: new Set(),
|
|
356
356
|
activeEntityRevision: 2,
|
|
357
357
|
})
|
|
@@ -377,7 +377,7 @@ describe('GPU-driven production projection', () => {
|
|
|
377
377
|
]),
|
|
378
378
|
viewBindGroupLayout: viewLayout,
|
|
379
379
|
meshResidencyEpoch: 1,
|
|
380
|
-
|
|
380
|
+
|
|
381
381
|
activeEntityKeys: new Set([worldEntityKey(0, 1)]),
|
|
382
382
|
activeEntityRevision: 3,
|
|
383
383
|
})
|
|
@@ -433,7 +433,7 @@ describe('GPU-driven production projection', () => {
|
|
|
433
433
|
meshBySlot: new Map([[0, mesh(device)]]),
|
|
434
434
|
viewBindGroupLayout: viewLayout,
|
|
435
435
|
meshResidencyEpoch: 1,
|
|
436
|
-
|
|
436
|
+
|
|
437
437
|
activeEntityKeys: new Set(),
|
|
438
438
|
activeEntityRevision: 1,
|
|
439
439
|
})
|
|
@@ -491,7 +491,6 @@ describe('GPU-driven production projection', () => {
|
|
|
491
491
|
]),
|
|
492
492
|
viewBindGroupLayout: viewLayout,
|
|
493
493
|
meshResidencyEpoch: 1,
|
|
494
|
-
hdrp: false,
|
|
495
494
|
})
|
|
496
495
|
.unwrap();
|
|
497
496
|
expect(prepared).toBeDefined();
|
|
@@ -586,7 +585,6 @@ describe('GPU-driven production projection', () => {
|
|
|
586
585
|
]),
|
|
587
586
|
viewBindGroupLayout: viewLayout,
|
|
588
587
|
meshResidencyEpoch: 1,
|
|
589
|
-
hdrp: false,
|
|
590
588
|
})
|
|
591
589
|
.unwrap();
|
|
592
590
|
expect(prepared).toBeDefined();
|
|
@@ -744,7 +742,6 @@ describe('GPU-driven production projection', () => {
|
|
|
744
742
|
meshBySlot: meshes,
|
|
745
743
|
viewBindGroupLayout: viewLayout,
|
|
746
744
|
meshResidencyEpoch: 1,
|
|
747
|
-
hdrp: false,
|
|
748
745
|
})
|
|
749
746
|
.unwrap();
|
|
750
747
|
expect(prepared).toBeDefined();
|
|
@@ -776,7 +773,6 @@ describe('GPU-driven production projection', () => {
|
|
|
776
773
|
meshBySlot: meshes,
|
|
777
774
|
viewBindGroupLayout: viewLayout,
|
|
778
775
|
meshResidencyEpoch: 1,
|
|
779
|
-
hdrp: false,
|
|
780
776
|
})
|
|
781
777
|
.unwrap();
|
|
782
778
|
expect(stable?.topologySignature).toBe(prepared.topologySignature);
|
|
@@ -809,7 +805,6 @@ describe('GPU-driven production projection', () => {
|
|
|
809
805
|
meshBySlot: meshes,
|
|
810
806
|
viewBindGroupLayout: viewLayout,
|
|
811
807
|
meshResidencyEpoch: 1,
|
|
812
|
-
hdrp: false,
|
|
813
808
|
})
|
|
814
809
|
.unwrap();
|
|
815
810
|
expect(moved).toBeDefined();
|
|
@@ -892,7 +887,7 @@ describe('GPU-driven production projection', () => {
|
|
|
892
887
|
meshBySlot: meshes,
|
|
893
888
|
viewBindGroupLayout: viewLayout,
|
|
894
889
|
meshResidencyEpoch: 1,
|
|
895
|
-
|
|
890
|
+
|
|
896
891
|
activeEntityKeys: new Set([worldEntityKey(0, 1)]),
|
|
897
892
|
activeEntityRevision: 1,
|
|
898
893
|
})
|
|
@@ -912,7 +907,7 @@ describe('GPU-driven production projection', () => {
|
|
|
912
907
|
meshBySlot: meshes,
|
|
913
908
|
viewBindGroupLayout: viewLayout,
|
|
914
909
|
meshResidencyEpoch: 1,
|
|
915
|
-
|
|
910
|
+
|
|
916
911
|
activeEntityKeys: new Set([worldEntityKey(1, 2)]),
|
|
917
912
|
activeEntityRevision: 2,
|
|
918
913
|
})
|
|
@@ -939,7 +934,6 @@ describe('GPU-driven production projection', () => {
|
|
|
939
934
|
meshBySlot: meshes,
|
|
940
935
|
viewBindGroupLayout: viewLayout,
|
|
941
936
|
meshResidencyEpoch: 1,
|
|
942
|
-
hdrp: false,
|
|
943
937
|
})
|
|
944
938
|
.unwrap();
|
|
945
939
|
expect(replacementPrepared?.topologySignature).not.toBe(prepared.topologySignature);
|
|
@@ -982,7 +976,6 @@ describe('GPU-driven production projection', () => {
|
|
|
982
976
|
},
|
|
983
977
|
meshBySlot: new Map([[0, mesh(device)]]),
|
|
984
978
|
viewBindGroupLayout: viewLayout,
|
|
985
|
-
hdrp: false,
|
|
986
979
|
} as const;
|
|
987
980
|
|
|
988
981
|
expect(
|
|
@@ -1353,7 +1346,7 @@ describe('GPU-driven production projection', () => {
|
|
|
1353
1346
|
meshBySlot: new Map([[0, mesh(device)]]),
|
|
1354
1347
|
viewBindGroupLayout: viewLayout,
|
|
1355
1348
|
meshResidencyEpoch: 1,
|
|
1356
|
-
|
|
1349
|
+
|
|
1357
1350
|
standardPbrArtifact: artifact,
|
|
1358
1351
|
standardPbrPipelineState: {
|
|
1359
1352
|
pbrPipelineLayout,
|
|
@@ -1461,7 +1454,7 @@ describe('GPU-driven production projection', () => {
|
|
|
1461
1454
|
const gpuKey = gpuDrivenShadowDrawKey(entity, -1, 0, 0);
|
|
1462
1455
|
const residualKey = gpuDrivenShadowDrawKey(entity, 22, 1, 0);
|
|
1463
1456
|
const allShadowKeys = new Set([gpuKey, residualKey]);
|
|
1464
|
-
const prepareFrame = (
|
|
1457
|
+
const prepareFrame = () =>
|
|
1465
1458
|
production
|
|
1466
1459
|
.prepare({
|
|
1467
1460
|
scene: {
|
|
@@ -1473,7 +1466,6 @@ describe('GPU-driven production projection', () => {
|
|
|
1473
1466
|
meshBySlot: new Map([[0, mesh(device)]]),
|
|
1474
1467
|
viewBindGroupLayout: viewLayout,
|
|
1475
1468
|
meshResidencyEpoch: 1,
|
|
1476
|
-
hdrp,
|
|
1477
1469
|
standardPbrArtifact: artifact,
|
|
1478
1470
|
standardPbrPipelineState: {
|
|
1479
1471
|
pbrPipelineLayout,
|
|
@@ -1487,7 +1479,7 @@ describe('GPU-driven production projection', () => {
|
|
|
1487
1479
|
shadowCasterDrawKeys: allShadowKeys,
|
|
1488
1480
|
})
|
|
1489
1481
|
.unwrap();
|
|
1490
|
-
const prepared = prepareFrame(
|
|
1482
|
+
const prepared = prepareFrame();
|
|
1491
1483
|
expect(prepared).toBeDefined();
|
|
1492
1484
|
if (prepared === undefined) return;
|
|
1493
1485
|
const claimed = new Set(prepared.shadowDrawKeys ?? []);
|
|
@@ -1521,11 +1513,7 @@ describe('GPU-driven production projection', () => {
|
|
|
1521
1513
|
);
|
|
1522
1514
|
const submission = prepared.shadowViewPool?.submission(identity);
|
|
1523
1515
|
expect(submission?.plan.candidateCount).toBe(1);
|
|
1524
|
-
|
|
1525
|
-
expect(production.inspect().channels.filter((channel) => channel.viewPass !== 'main')).toEqual(
|
|
1526
|
-
[],
|
|
1527
|
-
);
|
|
1528
|
-
const resumed = prepareFrame(false);
|
|
1516
|
+
const resumed = prepareFrame();
|
|
1529
1517
|
expect(
|
|
1530
1518
|
resumed?.updateShadowViews?.([
|
|
1531
1519
|
{ identity, planes: new Float32Array(24), cacheToken: 'mixed-candidates' },
|
|
@@ -1684,7 +1672,7 @@ describe('GPU-driven production projection', () => {
|
|
|
1684
1672
|
meshBySlot: new Map([[0, multiMesh]]),
|
|
1685
1673
|
viewBindGroupLayout: viewLayout,
|
|
1686
1674
|
meshResidencyEpoch: 1,
|
|
1687
|
-
|
|
1675
|
+
|
|
1688
1676
|
standardPbrArtifact: artifact,
|
|
1689
1677
|
standardPbrPipelineState: {
|
|
1690
1678
|
pbrPipelineLayout,
|
|
@@ -1906,7 +1894,7 @@ describe('GPU-driven production projection', () => {
|
|
|
1906
1894
|
instanceBuffers: new Map(),
|
|
1907
1895
|
meshBindGroupCache: new Map(),
|
|
1908
1896
|
instancesBgPerEntity: new Map(),
|
|
1909
|
-
|
|
1897
|
+
shadowMaterialBindGroups: new WeakMap(),
|
|
1910
1898
|
materialBgShared: new Map(),
|
|
1911
1899
|
},
|
|
1912
1900
|
materialBgAssemblyCache: new Map(),
|