@forgeax/engine-render 0.1.23 → 0.1.25
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 +231 -10
- package/dist/assembly/bundler-contract.d.ts +9 -0
- package/dist/assembly/bundler-contract.d.ts.map +1 -0
- package/dist/assembly/device-feature-admission.d.ts +8 -0
- package/dist/assembly/device-feature-admission.d.ts.map +1 -1
- package/dist/assembly/extended-lighting-fallback.d.ts +13 -0
- package/dist/assembly/extended-lighting-fallback.d.ts.map +1 -0
- package/dist/assembly/factory.d.ts +7 -243
- package/dist/assembly/factory.d.ts.map +1 -1
- package/dist/assembly/material/assembly.d.ts +3 -2
- package/dist/assembly/material/assembly.d.ts.map +1 -1
- package/dist/assembly/material/standard-layer-projection.d.ts +10 -0
- package/dist/assembly/material/standard-layer-projection.d.ts.map +1 -0
- package/dist/assembly/material/surface-projection.d.ts +24 -0
- package/dist/assembly/material/surface-projection.d.ts.map +1 -0
- package/dist/assembly/material-shader-policy.d.ts +188 -0
- package/dist/assembly/material-shader-policy.d.ts.map +1 -0
- package/dist/assembly/material-shader-prewarm.d.ts +21 -0
- package/dist/assembly/material-shader-prewarm.d.ts.map +1 -0
- package/dist/assembly/mesh-ssbo-grow.d.ts +88 -0
- package/dist/assembly/mesh-ssbo-grow.d.ts.map +1 -0
- package/dist/assembly/recovery/device-loss-fanout.d.ts +14 -0
- package/dist/assembly/recovery/device-loss-fanout.d.ts.map +1 -0
- package/dist/assembly/recovery/generation.d.ts +46 -0
- package/dist/assembly/recovery/generation.d.ts.map +1 -0
- package/dist/assembly/recovery/recovery-attempt.d.ts +63 -0
- package/dist/assembly/recovery/recovery-attempt.d.ts.map +1 -0
- package/dist/assembly/recovery/renderer-recover.d.ts +115 -0
- package/dist/assembly/recovery/renderer-recover.d.ts.map +1 -0
- package/dist/assembly/renderer-facade.d.ts +10 -0
- package/dist/assembly/renderer-facade.d.ts.map +1 -0
- package/dist/assembly/renderer-frame-transaction.d.ts +17 -0
- package/dist/assembly/renderer-frame-transaction.d.ts.map +1 -1
- package/dist/assembly/renderer-helpers.d.ts +19 -0
- package/dist/assembly/renderer-helpers.d.ts.map +1 -0
- package/dist/assembly/renderer-lifecycle.d.ts +34 -0
- package/dist/assembly/renderer-lifecycle.d.ts.map +1 -1
- package/dist/assembly/shader-prewarm-policy.d.ts +15 -0
- package/dist/assembly/shader-prewarm-policy.d.ts.map +1 -0
- package/dist/assembly/webgpu-ready-contract.d.ts +9 -0
- package/dist/assembly/webgpu-ready-contract.d.ts.map +1 -0
- package/dist/assembly/webgpu-ready.d.ts +55 -0
- package/dist/assembly/webgpu-ready.d.ts.map +1 -0
- package/dist/assembly/webgpu-renderer.d.ts +152 -0
- package/dist/assembly/webgpu-renderer.d.ts.map +1 -0
- package/dist/assembly/webgpu-vertex-layouts.d.ts +89 -0
- package/dist/assembly/webgpu-vertex-layouts.d.ts.map +1 -0
- package/dist/assets/asset-decoders.d.ts.map +1 -1
- package/dist/authoring.mjs +1 -1
- package/dist/{chunk-FF7K3FSO.mjs → chunk-ADHHVYLW.mjs} +89 -89
- package/dist/chunk-ADHHVYLW.mjs.map +1 -0
- package/dist/{chunk-YALPS44A.mjs → chunk-E34VL5VI.mjs} +47 -47
- package/dist/chunk-E34VL5VI.mjs.map +1 -0
- package/dist/{chunk-4L3P6DT5.mjs → chunk-GE3SDD72.mjs} +37 -5
- package/dist/chunk-GE3SDD72.mjs.map +1 -0
- package/dist/{chunk-HZUPSYW7.mjs → chunk-HKXTW355.mjs} +105 -15
- package/dist/chunk-HKXTW355.mjs.map +1 -0
- package/dist/chunk-JSEDTZYS.mjs +413 -0
- package/dist/chunk-JSEDTZYS.mjs.map +1 -0
- package/dist/{chunk-FBC4R44J.mjs → chunk-KM2NOX2I.mjs} +57 -57
- package/dist/chunk-KM2NOX2I.mjs.map +1 -0
- package/dist/{chunk-DIYW3M5D.mjs → chunk-N3RT2EUR.mjs} +2288 -2238
- package/dist/chunk-N3RT2EUR.mjs.map +1 -0
- package/dist/{chunk-ZUWKAZ2I.mjs → chunk-TCLDX7SZ.mjs} +1167 -368
- package/dist/chunk-TCLDX7SZ.mjs.map +1 -0
- package/dist/{chunk-QODA5UKU.mjs → chunk-ZZ4YQ474.mjs} +2 -2
- package/dist/chunk-ZZ4YQ474.mjs.map +1 -0
- package/dist/components/instances.d.ts +13 -31
- package/dist/components/instances.d.ts.map +1 -1
- package/dist/construct-renderer.mjs +20688 -16314
- 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 +24 -4
- package/dist/device/gpu-residency.d.ts.map +1 -1
- package/dist/environment/frame.d.ts +5 -0
- package/dist/environment/frame.d.ts.map +1 -1
- package/dist/environment/inspection.d.ts +7 -0
- package/dist/environment/inspection.d.ts.map +1 -1
- package/dist/environment/lifecycle.d.ts +20 -2
- package/dist/environment/lifecycle.d.ts.map +1 -1
- package/dist/errors/recover.d.ts +58 -2
- package/dist/errors/recover.d.ts.map +1 -1
- package/dist/errors/render.d.ts +13 -0
- package/dist/errors/render.d.ts.map +1 -1
- package/dist/extract/contracts.d.ts +899 -0
- package/dist/extract/contracts.d.ts.map +1 -0
- package/dist/features/host.d.ts +2 -0
- package/dist/features/host.d.ts.map +1 -1
- package/dist/features/prepared-gpu-work.d.ts +3 -0
- package/dist/features/prepared-gpu-work.d.ts.map +1 -1
- package/dist/features/prepared-graphics-store.d.ts +2 -0
- package/dist/features/prepared-graphics-store.d.ts.map +1 -1
- package/dist/gpu-driven/production-raster.d.ts +34 -1
- package/dist/gpu-driven/production-raster.d.ts.map +1 -1
- package/dist/gpu-scene.d.ts +5 -0
- package/dist/gpu-scene.d.ts.map +1 -1
- package/dist/ibl/IblPipelineCache.d.ts +7 -6
- package/dist/ibl/IblPipelineCache.d.ts.map +1 -1
- package/dist/ibl/skylight-bind-group.d.ts +7 -1
- package/dist/ibl/skylight-bind-group.d.ts.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +27 -9
- package/dist/index.mjs.map +1 -1
- package/dist/instance-buffer-cache.d.ts +7 -1
- package/dist/instance-buffer-cache.d.ts.map +1 -1
- package/dist/instances.d.ts +101 -0
- package/dist/instances.d.ts.map +1 -0
- package/dist/internal.mjs +6 -6
- package/dist/light-buffer-layout.d.ts +3 -0
- package/dist/light-buffer-layout.d.ts.map +1 -1
- package/dist/materials.d.ts +96 -11
- package/dist/materials.d.ts.map +1 -1
- package/dist/mesh-material-bindings.d.ts +56 -0
- package/dist/mesh-material-bindings.d.ts.map +1 -1
- package/dist/occlusion-proxy.d.ts +4 -0
- package/dist/occlusion-proxy.d.ts.map +1 -0
- package/dist/pbr-pipeline.d.ts +32 -9
- package/dist/pbr-pipeline.d.ts.map +1 -1
- package/dist/pipeline-builder.d.ts.map +1 -1
- package/dist/pipeline-spec.d.ts.map +1 -1
- package/dist/points-lines/prepare.d.ts +3 -0
- package/dist/points-lines/prepare.d.ts.map +1 -1
- package/dist/points-lines/standard-owner.d.ts +33 -0
- package/dist/points-lines/standard-owner.d.ts.map +1 -0
- package/dist/record/frame-snapshot.d.ts +18 -2
- package/dist/record/frame-snapshot.d.ts.map +1 -1
- package/dist/record/frame-targets.d.ts.map +1 -1
- package/dist/record/frame.d.ts +14 -2
- package/dist/record/frame.d.ts.map +1 -1
- package/dist/record/main-pass-geometry.d.ts +36 -4
- package/dist/record/main-pass-geometry.d.ts.map +1 -1
- package/dist/record/main-pass-material.d.ts +7 -17
- package/dist/record/main-pass-material.d.ts.map +1 -1
- package/dist/record/main-pass.d.ts.map +1 -1
- package/dist/record/mesh-ssbo.d.ts +11 -3
- package/dist/record/mesh-ssbo.d.ts.map +1 -1
- package/dist/record/recovery-pipeline.d.ts +30 -0
- package/dist/record/recovery-pipeline.d.ts.map +1 -0
- package/dist/record/render-context.d.ts +28 -5
- package/dist/record/render-context.d.ts.map +1 -1
- package/dist/record/shadow-pass.d.ts +11 -1
- package/dist/record/shadow-pass.d.ts.map +1 -1
- package/dist/record/typed-frame-graph.d.ts +1 -1
- package/dist/record/typed-frame-graph.d.ts.map +1 -1
- package/dist/recovery/render-system-candidate.d.ts +65 -0
- package/dist/recovery/render-system-candidate.d.ts.map +1 -0
- package/dist/render-contract.d.ts +68 -7
- package/dist/render-contract.d.ts.map +1 -1
- package/dist/render-system-extract-tail.d.ts +16 -0
- package/dist/render-system-extract-tail.d.ts.map +1 -0
- package/dist/render-system-extract.d.ts +180 -22
- package/dist/render-system-extract.d.ts.map +1 -1
- package/dist/render-system.d.ts +131 -4
- package/dist/render-system.d.ts.map +1 -1
- package/dist/scene/render-scene-types.d.ts +2 -0
- package/dist/scene/render-scene-types.d.ts.map +1 -1
- package/dist/scene/render-scene.d.ts +31 -1
- package/dist/scene/render-scene.d.ts.map +1 -1
- package/dist/systems/skin-palette-allocator.d.ts +6 -0
- package/dist/systems/skin-palette-allocator.d.ts.map +1 -1
- package/dist/temporal/frame-coordinator.d.ts.map +1 -1
- package/dist/temporal/index.mjs +6 -6
- package/dist/temporal/taa-history-store.d.ts +15 -1
- package/dist/temporal/taa-history-store.d.ts.map +1 -1
- package/dist/temporal/transaction.d.ts +5 -0
- package/dist/temporal/transaction.d.ts.map +1 -1
- package/package.json +20 -20
- package/src/__tests__/device-feature-admission.unit.test.ts +6 -0
- package/src/__tests__/device-loss-fanout.unit.test.ts +107 -0
- package/src/__tests__/device-scope-lifecycle.unit.test.ts +21 -0
- package/src/__tests__/environment-generation.integration.test.ts +23 -0
- package/src/__tests__/expose-renderer-errors.unit.test.ts +34 -0
- package/src/__tests__/factory-contract.integration.test.ts +122 -7
- package/src/__tests__/fallback-row-stride-surface.unit.test.ts +4 -1
- package/src/__tests__/gpu-scene.unit.test.ts +38 -2
- package/src/__tests__/ibl/face-uniforms.unit.test.ts +2 -0
- package/src/__tests__/ibl-residency-publication.unit.test.ts +113 -0
- package/src/__tests__/instances-store.unit.test.ts +46 -0
- package/src/__tests__/instances-world-ownership.integration.test.ts +62 -0
- package/src/__tests__/material-contract-inventory.unit.test.ts +29 -22
- package/src/__tests__/material-cooked-projection.unit.test.ts +19 -1
- package/src/__tests__/material-pass-policy.unit.test.ts +69 -0
- package/src/__tests__/material-snapshot-mutation.integration.test.ts +69 -0
- package/src/__tests__/material-static-dynamic-route.unit.test.ts +29 -0
- package/src/__tests__/material-stride-surface.unit.test.ts +7 -3
- package/src/__tests__/material-surface-authoring.test-d.ts +62 -0
- package/src/__tests__/materials-standard-contract.unit.test.ts +104 -0
- package/src/__tests__/materials-transmission-validation.unit.test.ts +24 -0
- package/src/__tests__/mesh-buffer-usage-surface.unit.test.ts +1 -5
- package/src/__tests__/physical-clearcoat.integration.test.ts +89 -0
- package/src/__tests__/prepared-gpu-driven-pbr.integration.test.ts +1 -1
- package/src/__tests__/prepared-graphics-pipeline-warmup.unit.test.ts +1 -1
- package/src/__tests__/recover-error-policy-owner.unit.test.ts +6 -3
- package/src/__tests__/recovery-candidate-prepare.contract.test.ts +140 -0
- package/src/__tests__/renderer-factory-material-contract.unit.test.ts +127 -18
- package/src/__tests__/renderer-frame-generation-fence.integration.test.ts +47 -0
- package/src/__tests__/renderer-generation-assembly.unit.test.ts +77 -0
- package/src/__tests__/renderer-generation-failure.unit.test.ts +108 -0
- package/src/__tests__/renderer-producer-root-matrix.integration.test.ts +33 -0
- package/src/__tests__/renderer-recovery-capability-matrix.unit.test.ts +59 -0
- package/src/__tests__/renderer-recovery-contract.unit.test.ts +73 -0
- package/src/__tests__/renderer-recovery-lifecycle.unit.test.ts +216 -0
- package/src/__tests__/renderer-target-history-recovery.integration.test.ts +80 -0
- package/src/__tests__/shader-manifest-fixture.ts +13 -16
- package/src/__tests__/shader-stage-surface.unit.test.ts +1 -1
- package/src/__tests__/skin-motion-regression.unit.test.ts +33 -0
- package/src/__tests__/skinned-shadow-caster.test.ts +30 -2
- package/src/__tests__/standard-layer-projection.unit.test.ts +23 -0
- package/src/__tests__/surface-adjacent-regressions.integration.test.ts +60 -0
- package/src/__tests__/surface-standard-pipeline.browser.test.ts +20 -0
- package/src/__tests__/surface-standard-pipeline.dawn.test.ts +20 -0
- package/src/__tests__/surface-standard-pipeline.fixture.ts +132 -0
- package/src/__tests__/surface-variant-provenance.integration.test.ts +33 -0
- package/src/__tests__/transmission-prewarm.unit.test.ts +95 -85
- package/src/__tests__/volumetric-fog-budget-recovery.integration.test.ts +1 -1
- package/src/__tests__/volumetric-fog-topology.unit.test.ts +3 -1
- package/src/assembly/bundler-contract.ts +9 -0
- package/src/assembly/device-feature-admission.ts +15 -5
- package/src/assembly/extended-lighting-fallback.ts +216 -0
- package/src/assembly/factory.ts +83 -10088
- package/src/assembly/material/__tests__/standard-layer-plan-projection.integration.test.ts +18 -0
- package/src/assembly/material/__tests__/surface-pass-projection.integration.test.ts +62 -0
- package/src/assembly/material/assembly.ts +18 -2
- package/src/assembly/material/standard-layer-projection.ts +16 -0
- package/src/assembly/material/surface-projection.ts +90 -0
- package/src/assembly/material-shader-policy.ts +932 -0
- package/src/assembly/material-shader-prewarm.ts +88 -0
- package/src/assembly/mesh-ssbo-grow.ts +270 -0
- package/src/assembly/recovery/device-loss-fanout.ts +89 -0
- package/src/assembly/recovery/generation.ts +141 -0
- package/src/assembly/recovery/recovery-attempt.ts +800 -0
- package/src/assembly/recovery/renderer-recover.ts +906 -0
- package/src/assembly/renderer-facade.ts +342 -0
- package/src/assembly/renderer-frame-transaction.ts +45 -0
- package/src/assembly/renderer-helpers.ts +99 -0
- package/src/assembly/renderer-lifecycle.ts +159 -0
- package/src/assembly/shader-prewarm-policy.ts +157 -0
- package/src/assembly/webgpu-ready-contract.ts +14 -0
- package/src/assembly/webgpu-ready.ts +4066 -0
- package/src/assembly/webgpu-renderer.ts +4027 -0
- package/src/assembly/webgpu-vertex-layouts.ts +132 -0
- package/src/assets/asset-decoders.ts +27 -4
- package/src/components/camera.ts +1 -1
- package/src/components/instances.ts +14 -197
- package/src/debug-draw-glue.ts +1 -1
- package/src/device/device-scope.ts +35 -6
- package/src/device/gpu-residency.ts +194 -26
- package/src/environment/frame.ts +6 -0
- package/src/environment/inspection.ts +10 -0
- package/src/environment/lifecycle.ts +114 -8
- package/src/errors/recover.ts +76 -5
- package/src/errors/render.ts +17 -0
- package/src/extract/contracts.ts +974 -0
- package/src/features/host.ts +16 -0
- package/src/features/prepared-gpu-work.ts +20 -2
- package/src/features/prepared-graphics-store.ts +17 -0
- package/src/gpu-driven/production-raster.ts +131 -3
- package/src/gpu-scene.ts +87 -31
- package/src/ibl/IblPipelineCache.ts +134 -50
- package/src/ibl/skylight-bind-group.ts +26 -0
- package/src/index.ts +10 -1
- package/src/instance-buffer-cache.ts +14 -1
- package/src/instances.ts +288 -0
- package/src/light-buffer-layout.ts +3 -0
- package/src/materials.ts +365 -53
- package/src/mesh-material-bindings.ts +59 -0
- package/src/occlusion-proxy.ts +64 -0
- package/src/pbr-pipeline.ts +139 -15
- package/src/pipeline-builder.ts +14 -10
- package/src/pipeline-spec.ts +6 -14
- package/src/points-lines/__tests__/cache-recovery.unit.test.ts +22 -0
- package/src/points-lines/prepare.ts +9 -0
- package/src/points-lines/standard-owner.ts +403 -0
- package/src/record/__tests__/frame-targets-recovery.unit.test.ts +60 -0
- package/src/record/__tests__/main-pass-geometry.unit.test.ts +26 -1
- package/src/record/__tests__/mesh-ssbo.unit.test.ts +38 -0
- package/src/record/__tests__/recovery-pipeline.unit.test.ts +124 -0
- package/src/record/__tests__/sprite-material-abi.unit.test.ts +28 -13
- package/src/record/__tests__/standard-pbr-ubo-layout.unit.test.ts +47 -4
- package/src/record/__tests__/temporal-payload.unit.test.ts +22 -43
- package/src/record/__tests__/typed-frame-graph-plan.unit.test.ts +1 -1
- package/src/record/frame-snapshot.ts +34 -2
- package/src/record/frame-targets.ts +11 -1
- package/src/record/frame.ts +37 -4
- package/src/record/helpers.ts +1 -1
- package/src/record/main-pass-geometry.ts +727 -63
- package/src/record/main-pass-material.ts +316 -209
- package/src/record/main-pass-sprite-draws.ts +7 -8
- package/src/record/main-pass.ts +94 -6
- package/src/record/mesh-ssbo.ts +32 -10
- package/src/record/recovery-pipeline.ts +695 -0
- package/src/record/render-context.ts +39 -4
- package/src/record/shadow-pass.ts +46 -99
- package/src/record/typed-frame-graph.ts +45 -1
- package/src/record/view-ubo.ts +3 -3
- package/src/recovery/render-system-candidate.ts +876 -0
- package/src/render-contract.ts +69 -7
- package/src/render-system-extract-tail.ts +3039 -0
- package/src/render-system-extract.ts +177 -3003
- package/src/render-system.ts +906 -662
- package/src/scene/render-scene-types.ts +2 -0
- package/src/scene/render-scene.ts +703 -37
- package/src/systems/skin-palette-allocator.ts +129 -7
- package/src/temporal/frame-coordinator.ts +4 -1
- package/src/temporal/taa-history-store.ts +46 -2
- package/src/temporal/temporal-view.ts +1 -1
- package/src/temporal/transaction.ts +9 -0
- package/src/tilemap-chunk-extract-system.ts +1 -1
- package/src/transmission/__tests__/standard-transmission.dawn.test.ts +19 -12
- package/src/transmission/__tests__/surface-compatibility.integration.test.ts +32 -0
- package/dist/chunk-4L3P6DT5.mjs.map +0 -1
- package/dist/chunk-4NPUASZR.mjs +0 -203
- package/dist/chunk-4NPUASZR.mjs.map +0 -1
- package/dist/chunk-DIYW3M5D.mjs.map +0 -1
- package/dist/chunk-FBC4R44J.mjs.map +0 -1
- package/dist/chunk-FF7K3FSO.mjs.map +0 -1
- package/dist/chunk-HZUPSYW7.mjs.map +0 -1
- package/dist/chunk-QODA5UKU.mjs.map +0 -1
- package/dist/chunk-YALPS44A.mjs.map +0 -1
- package/dist/chunk-ZUWKAZ2I.mjs.map +0 -1
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { projectStandardSurfacePasses } from '../assembly/material/surface-projection';
|
|
3
|
+
import { layerPlanFor, passFor, SURFACE_CASES } from './surface-standard-pipeline.fixture';
|
|
4
|
+
|
|
5
|
+
describe('Standard Surface render projection contract', () => {
|
|
6
|
+
it('keeps physical roots Forward-only while base roots remain Deferred', () => {
|
|
7
|
+
for (const surfaceCase of SURFACE_CASES) {
|
|
8
|
+
const passes = projectStandardSurfacePasses({
|
|
9
|
+
surfaceModule: surfaceCase.surfaceModule,
|
|
10
|
+
values: surfaceCase.material.values ?? {},
|
|
11
|
+
geometryVariant: 'skinned',
|
|
12
|
+
lightingLane: 'clustered',
|
|
13
|
+
alphaClip: true,
|
|
14
|
+
layerPlan: layerPlanFor(surfaceCase),
|
|
15
|
+
});
|
|
16
|
+
expect(passes.some((entry) => entry.name === passFor(surfaceCase))).toBe(true);
|
|
17
|
+
expect(passes[0]?.program.moduleSlots?.surface).toBe(surfaceCase.surfaceModule);
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
});
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { AssetGuid, type PackageId } from '@forgeax/engine-pack/guid';
|
|
2
|
+
import type { MaterialAsset } from '@forgeax/engine-types';
|
|
3
|
+
import { deriveStandardLayerPlan } from '@forgeax/engine-types';
|
|
4
|
+
|
|
5
|
+
type SurfacePack = {
|
|
6
|
+
packageId: PackageId;
|
|
7
|
+
build: () =>
|
|
8
|
+
| { readonly ok: true; readonly value: Readonly<Record<string, MaterialAsset>> }
|
|
9
|
+
| Promise<{ readonly ok: true; readonly value: Readonly<Record<string, MaterialAsset>> }>;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
type ViteImportMeta = ImportMeta & {
|
|
13
|
+
glob<T>(
|
|
14
|
+
patterns: readonly string[],
|
|
15
|
+
options: { readonly eager: true; readonly import: 'default' },
|
|
16
|
+
): Readonly<Record<string, T>>;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const packModules = Object.values(
|
|
20
|
+
(import.meta as ViteImportMeta).glob<SurfacePack>(
|
|
21
|
+
[
|
|
22
|
+
'../../../../templates/game-3d/assets/materials.pack.ts',
|
|
23
|
+
'../../../../apps/preview/assets/surface-standard-evidence.pack.ts',
|
|
24
|
+
],
|
|
25
|
+
{
|
|
26
|
+
eager: true,
|
|
27
|
+
import: 'default',
|
|
28
|
+
},
|
|
29
|
+
),
|
|
30
|
+
);
|
|
31
|
+
if (packModules.length !== 2)
|
|
32
|
+
throw new Error('surface-evidence-fixture: required pack module missing');
|
|
33
|
+
|
|
34
|
+
const builtPacks = packModules.map((pack) => {
|
|
35
|
+
const built = pack.build();
|
|
36
|
+
if (built instanceof Promise || !built.ok) {
|
|
37
|
+
throw new Error('surface-evidence-fixture: materials pack did not produce outputs');
|
|
38
|
+
}
|
|
39
|
+
return { packageId: pack.packageId, values: built.value };
|
|
40
|
+
});
|
|
41
|
+
const materials = Object.assign({}, ...builtPacks.map((pack) => pack.values)) as Record<
|
|
42
|
+
string,
|
|
43
|
+
MaterialAsset | undefined
|
|
44
|
+
>;
|
|
45
|
+
|
|
46
|
+
function guidForSourceKey(sourceKey: string): AssetGuid {
|
|
47
|
+
const owner = builtPacks.find((pack) => Object.hasOwn(pack.values, sourceKey));
|
|
48
|
+
if (owner === undefined) {
|
|
49
|
+
throw new Error(`surface-evidence-fixture: source key '${sourceKey}' is not published`);
|
|
50
|
+
}
|
|
51
|
+
return AssetGuid.derive(owner.packageId, sourceKey);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const rustedIron = materials['material/rusted-iron'];
|
|
55
|
+
|
|
56
|
+
const defaultBase = materials['material/ground'];
|
|
57
|
+
const defaultPhysical = materials['material/painted'];
|
|
58
|
+
const customPhysical = materials['material/rusted-iron-custom-physical'];
|
|
59
|
+
if (
|
|
60
|
+
rustedIron === undefined ||
|
|
61
|
+
defaultBase === undefined ||
|
|
62
|
+
defaultPhysical === undefined ||
|
|
63
|
+
customPhysical === undefined
|
|
64
|
+
)
|
|
65
|
+
throw new Error('surface-evidence-fixture: required material row missing');
|
|
66
|
+
|
|
67
|
+
export const SURFACE_CLOSURE = 'forgeax_material::surface_v1';
|
|
68
|
+
export const SURFACE_SOURCE_CLOSURE = [
|
|
69
|
+
'templates/game-3d/assets/materials.pack.ts',
|
|
70
|
+
'templates/game-3d/assets/shaders/rusted-iron.wgsl',
|
|
71
|
+
] as const;
|
|
72
|
+
export const SURFACE_SOURCE_PATH = 'templates/game-3d/assets/shaders/rusted-iron.wgsl';
|
|
73
|
+
export const SURFACE_MATERIAL_SOURCE_KEY = 'material/rusted-iron';
|
|
74
|
+
export const EVIDENCE_SOURCE_SHA =
|
|
75
|
+
(import.meta as ImportMeta & { env?: Record<string, string | undefined> }).env
|
|
76
|
+
?.VITE_FORGEAX_EVIDENCE_SOURCE_SHA ?? 'unavailable';
|
|
77
|
+
|
|
78
|
+
export const SURFACE_CASES = [
|
|
79
|
+
{
|
|
80
|
+
id: 'default-base',
|
|
81
|
+
material: defaultBase,
|
|
82
|
+
materialGuid: AssetGuid.format(guidForSourceKey('material/ground')),
|
|
83
|
+
surfaceModule: defaultBase.passes?.[0]?.program.moduleSlots?.surface ?? '',
|
|
84
|
+
physical: false,
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
id: 'custom-base',
|
|
88
|
+
material: rustedIron,
|
|
89
|
+
materialGuid: AssetGuid.format(guidForSourceKey('material/rusted-iron')),
|
|
90
|
+
surfaceModule: rustedIron.passes?.[0]?.program.moduleSlots?.surface ?? '',
|
|
91
|
+
physical: false,
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
id: 'default-physical',
|
|
95
|
+
material: defaultPhysical,
|
|
96
|
+
materialGuid: '019fb7ce-3200-7000-8000-000000000002',
|
|
97
|
+
surfaceModule: defaultPhysical.passes?.[0]?.program.moduleSlots?.surface ?? '',
|
|
98
|
+
physical: true,
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
id: 'custom-physical',
|
|
102
|
+
material: customPhysical,
|
|
103
|
+
materialGuid: '019fb7ce-3f00-7000-8000-000000000001',
|
|
104
|
+
surfaceModule: customPhysical.passes?.[0]?.program.moduleSlots?.surface ?? '',
|
|
105
|
+
physical: true,
|
|
106
|
+
},
|
|
107
|
+
] as const;
|
|
108
|
+
|
|
109
|
+
export function layerPlanFor(surfaceCase: (typeof SURFACE_CASES)[number]) {
|
|
110
|
+
return deriveStandardLayerPlan(
|
|
111
|
+
surfaceCase.physical ? (surfaceCase.material.parameters ?? []) : [],
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export function baseColorFor(
|
|
116
|
+
surfaceCase: (typeof SURFACE_CASES)[number],
|
|
117
|
+
): readonly [number, number, number] {
|
|
118
|
+
const values = surfaceCase.material.values ?? {};
|
|
119
|
+
const value = values.baseColor ?? values.ironColor;
|
|
120
|
+
if (!Array.isArray(value) || value.length < 3) {
|
|
121
|
+
throw new Error(`surface-evidence-fixture: missing base color for ${surfaceCase.id}`);
|
|
122
|
+
}
|
|
123
|
+
return [Number(value[0]), Number(value[1]), Number(value[2])];
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export function passFor(surfaceCase: (typeof SURFACE_CASES)[number]): 'forward' | 'deferred' {
|
|
127
|
+
return layerPlanFor(surfaceCase).mode === 'physical' ? 'forward' : 'deferred';
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export function publicationGenerationFor(_surfaceCase: (typeof SURFACE_CASES)[number]): number {
|
|
131
|
+
return 1;
|
|
132
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import {
|
|
3
|
+
projectStandardSurfacePasses,
|
|
4
|
+
type StandardSurfaceProjectionOptions,
|
|
5
|
+
} from '../assembly/material/surface-projection';
|
|
6
|
+
|
|
7
|
+
type FullCustomFixture = StandardSurfaceProjectionOptions & {
|
|
8
|
+
readonly surfaceKind: 'full-custom';
|
|
9
|
+
readonly declaredPasses: readonly ('forward' | 'deferred' | 'shadow-caster')[];
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
describe('full-custom Surface provenance', () => {
|
|
13
|
+
it('does not synthesize an undeclared Deferred pass or fallback identity', () => {
|
|
14
|
+
const options: FullCustomFixture = {
|
|
15
|
+
surfaceModule: 'game_3d::full_custom_surface',
|
|
16
|
+
values: { tint: [1, 0.1, 0.05, 1] },
|
|
17
|
+
surfaceKind: 'full-custom',
|
|
18
|
+
declaredPasses: ['forward', 'shadow-caster'],
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const passes = projectStandardSurfacePasses(options);
|
|
22
|
+
|
|
23
|
+
expect(passes.map((pass) => pass.name)).toEqual(['forward', 'shadow-caster']);
|
|
24
|
+
expect(passes.map((pass) => pass.program.module)).toEqual([
|
|
25
|
+
'forgeax_material::standard',
|
|
26
|
+
'forgeax_material::standard',
|
|
27
|
+
]);
|
|
28
|
+
for (const pass of passes) {
|
|
29
|
+
expect(pass.program.moduleSlots?.surface).toBe(options.surfaceModule);
|
|
30
|
+
expect((pass.renderState?.tags as Record<string, string>).SurfaceKind).toBe('full-custom');
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
});
|
|
@@ -2,6 +2,7 @@ import { describe, expect, it } from 'vitest';
|
|
|
2
2
|
import {
|
|
3
3
|
type MaterialShaderManifestEntry,
|
|
4
4
|
selectHdrpPbrPrewarmVariants,
|
|
5
|
+
selectProbePrewarmVariants,
|
|
5
6
|
selectStandardPbrTransmissionPrewarmVariants,
|
|
6
7
|
} from '../assembly/factory.js';
|
|
7
8
|
|
|
@@ -9,10 +10,6 @@ const falseKey =
|
|
|
9
10
|
'CLUSTER_FORWARD_AVAILABLE=false+STORAGE_BUFFER_AVAILABLE=true+TRANSMISSION_AVAILABLE=false+VERTEX_COLOR_AVAILABLE=false';
|
|
10
11
|
const trueKey =
|
|
11
12
|
'CLUSTER_FORWARD_AVAILABLE=false+STORAGE_BUFFER_AVAILABLE=true+TRANSMISSION_AVAILABLE=true+VERTEX_COLOR_AVAILABLE=false';
|
|
12
|
-
const hdrpFalseKey =
|
|
13
|
-
'CLUSTER_FORWARD_AVAILABLE=true+STORAGE_BUFFER_AVAILABLE=true+TRANSMISSION_AVAILABLE=false+VERTEX_COLOR_AVAILABLE=false';
|
|
14
|
-
const hdrpTrueKey =
|
|
15
|
-
'CLUSTER_FORWARD_AVAILABLE=true+STORAGE_BUFFER_AVAILABLE=true+TRANSMISSION_AVAILABLE=true+VERTEX_COLOR_AVAILABLE=false';
|
|
16
13
|
const probeFalseKey =
|
|
17
14
|
'CLUSTER_FORWARD_AVAILABLE=false+PROBE_BLEND_AVAILABLE=true+STORAGE_BUFFER_AVAILABLE=true+TRANSMISSION_AVAILABLE=false+VERTEX_COLOR_AVAILABLE=false';
|
|
18
15
|
const probeTrueKey =
|
|
@@ -30,29 +27,33 @@ function standardEntry(
|
|
|
30
27
|
};
|
|
31
28
|
}
|
|
32
29
|
|
|
33
|
-
function
|
|
30
|
+
function variant(cluster: boolean, storage: boolean, projector?: boolean) {
|
|
31
|
+
const defines = {
|
|
32
|
+
CLUSTER_FORWARD_AVAILABLE: cluster,
|
|
33
|
+
STORAGE_BUFFER_AVAILABLE: storage,
|
|
34
|
+
VERTEX_COLOR_AVAILABLE: false,
|
|
35
|
+
...(projector === undefined ? {} : { PROJECTOR_AVAILABLE: projector }),
|
|
36
|
+
};
|
|
34
37
|
return {
|
|
35
|
-
definesKey
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
},
|
|
42
|
-
composedWgsl: `standard-${transmission}`,
|
|
38
|
+
definesKey: Object.entries(defines)
|
|
39
|
+
.sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))
|
|
40
|
+
.map(([name, value]) => `${name}=${value}`)
|
|
41
|
+
.join('+'),
|
|
42
|
+
defines,
|
|
43
|
+
composedWgsl: JSON.stringify(defines),
|
|
43
44
|
};
|
|
44
45
|
}
|
|
45
46
|
|
|
46
|
-
function
|
|
47
|
+
function transmissionVariant(definesKey: string, transmission: boolean) {
|
|
47
48
|
return {
|
|
48
49
|
definesKey,
|
|
49
50
|
defines: {
|
|
50
|
-
CLUSTER_FORWARD_AVAILABLE:
|
|
51
|
+
CLUSTER_FORWARD_AVAILABLE: false,
|
|
51
52
|
STORAGE_BUFFER_AVAILABLE: true,
|
|
52
53
|
TRANSMISSION_AVAILABLE: transmission,
|
|
53
54
|
VERTEX_COLOR_AVAILABLE: false,
|
|
54
55
|
},
|
|
55
|
-
composedWgsl: `
|
|
56
|
+
composedWgsl: `standard-${transmission}`,
|
|
56
57
|
};
|
|
57
58
|
}
|
|
58
59
|
|
|
@@ -60,103 +61,112 @@ function probeTransmissionVariant(definesKey: string, transmission: boolean) {
|
|
|
60
61
|
const base = transmissionVariant(definesKey, transmission);
|
|
61
62
|
return {
|
|
62
63
|
...base,
|
|
63
|
-
definesKey,
|
|
64
64
|
defines: { ...base.defines, PROBE_BLEND_AVAILABLE: true },
|
|
65
65
|
};
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
function capabilityTransmissionVariant(
|
|
69
|
-
definesKey: string,
|
|
70
|
-
transmission: boolean,
|
|
71
|
-
extendedLighting: boolean,
|
|
72
|
-
) {
|
|
73
|
-
const base = transmissionVariant(definesKey, transmission);
|
|
74
|
-
return {
|
|
75
|
-
...base,
|
|
76
|
-
definesKey,
|
|
77
|
-
defines: {
|
|
78
|
-
...base.defines,
|
|
79
|
-
EXTENDED_LIGHTING_AVAILABLE: extendedLighting,
|
|
80
|
-
PROJECTOR_AVAILABLE: true,
|
|
81
|
-
},
|
|
82
|
-
composedWgsl: `standard-${extendedLighting ? 'extended' : 'fallback'}-${transmission}`,
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
|
|
86
68
|
describe('Standard transmission exact-key prewarm selection', () => {
|
|
87
|
-
it('returns both declared variants
|
|
69
|
+
it('returns both declared transmission variants', () => {
|
|
88
70
|
const entry = standardEntry([
|
|
89
71
|
transmissionVariant(falseKey, false),
|
|
90
72
|
transmissionVariant(trueKey, true),
|
|
91
73
|
]);
|
|
92
|
-
|
|
93
|
-
|
|
74
|
+
expect(
|
|
75
|
+
selectStandardPbrTransmissionPrewarmVariants(entry, true).map((item) => item.definesKey),
|
|
76
|
+
).toEqual([falseKey, trueKey]);
|
|
94
77
|
});
|
|
95
78
|
|
|
96
|
-
it('
|
|
79
|
+
it('rejects a missing exact transmission variant', () => {
|
|
97
80
|
const entry = standardEntry([transmissionVariant(falseKey, false)]);
|
|
98
81
|
expect(() => selectStandardPbrTransmissionPrewarmVariants(entry, true)).toThrow(
|
|
99
82
|
'TRANSMISSION_AVAILABLE=true',
|
|
100
83
|
);
|
|
101
84
|
});
|
|
85
|
+
});
|
|
102
86
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
'manifest row is missing',
|
|
106
|
-
);
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
it('keeps object-level probe variants out of the boot prewarm selection', () => {
|
|
87
|
+
describe('HDRP PBR capability prewarm selection', () => {
|
|
88
|
+
it('selects only the matching static capability/geometry state', () => {
|
|
110
89
|
const entry = standardEntry([
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
90
|
+
variant(true, true),
|
|
91
|
+
variant(true, false),
|
|
92
|
+
variant(false, true),
|
|
93
|
+
variant(false, false),
|
|
115
94
|
]);
|
|
116
|
-
expect(
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
95
|
+
expect(selectHdrpPbrPrewarmVariants(entry, true).map((item) => item.definesKey)).toEqual([
|
|
96
|
+
variant(true, true).definesKey,
|
|
97
|
+
]);
|
|
98
|
+
// Cluster-forward requires the storage-backed group(2) ABI. A device
|
|
99
|
+
// without storage support must stay on the URP route and prewarm nothing.
|
|
100
|
+
expect(selectHdrpPbrPrewarmVariants(entry, false)).toEqual([]);
|
|
121
101
|
});
|
|
122
102
|
|
|
123
|
-
it('
|
|
124
|
-
const fallbackFalseKey = `${falseKey}+EXTENDED_LIGHTING_AVAILABLE=false+PROJECTOR_AVAILABLE=true`;
|
|
125
|
-
const fallbackTrueKey = `${trueKey}+EXTENDED_LIGHTING_AVAILABLE=false+PROJECTOR_AVAILABLE=true`;
|
|
126
|
-
const extendedFalseKey = `${falseKey}+EXTENDED_LIGHTING_AVAILABLE=true+PROJECTOR_AVAILABLE=true`;
|
|
127
|
-
const extendedTrueKey = `${trueKey}+EXTENDED_LIGHTING_AVAILABLE=true+PROJECTOR_AVAILABLE=true`;
|
|
103
|
+
it('respects an explicitly declared projector capability', () => {
|
|
128
104
|
const entry = standardEntry([
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
capabilityTransmissionVariant(extendedTrueKey, true, true),
|
|
105
|
+
variant(true, true, true),
|
|
106
|
+
variant(true, true, false),
|
|
107
|
+
variant(true, true),
|
|
133
108
|
]);
|
|
134
|
-
|
|
135
109
|
expect(
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
),
|
|
139
|
-
).toEqual([fallbackFalseKey, fallbackTrueKey]);
|
|
140
|
-
expect(
|
|
141
|
-
selectStandardPbrTransmissionPrewarmVariants(entry, true, true, true, true).map(
|
|
142
|
-
(variant) => variant.definesKey,
|
|
143
|
-
),
|
|
144
|
-
).toEqual([extendedFalseKey, extendedTrueKey]);
|
|
110
|
+
selectHdrpPbrPrewarmVariants(entry, true, undefined, true).map((item) => item.definesKey),
|
|
111
|
+
).toEqual([variant(true, true, true).definesKey, variant(true, true).definesKey]);
|
|
145
112
|
});
|
|
146
113
|
});
|
|
147
114
|
|
|
148
|
-
describe('
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
).toEqual([
|
|
115
|
+
describe('probe material module prewarm capability selection', () => {
|
|
116
|
+
it('keeps probe variants out of the fallback tier and matches device-owned axes', () => {
|
|
117
|
+
const entry = standardEntry([
|
|
118
|
+
probeTransmissionVariant(probeFalseKey, false),
|
|
119
|
+
probeTransmissionVariant(probeTrueKey, true),
|
|
120
|
+
]);
|
|
121
|
+
expect(selectProbePrewarmVariants(entry, false)).toEqual([]);
|
|
122
|
+
expect(selectProbePrewarmVariants(entry, true).map((variant) => variant.definesKey)).toEqual([
|
|
123
|
+
probeFalseKey,
|
|
124
|
+
probeTrueKey,
|
|
125
|
+
]);
|
|
155
126
|
});
|
|
156
127
|
|
|
157
|
-
it('
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
128
|
+
it('filters backend and sampled-texture axes but retains geometry/topology choices', () => {
|
|
129
|
+
const goodKey =
|
|
130
|
+
'CLUSTER_FORWARD_AVAILABLE=true+EXTENDED_LIGHTING_AVAILABLE=false+PROBE_BLEND_AVAILABLE=true+PROJECTOR_AVAILABLE=false+STORAGE_BUFFER_AVAILABLE=true+TRANSMISSION_AVAILABLE=false+VERTEX_COLOR_AVAILABLE=true';
|
|
131
|
+
const wrongExtendedKey = goodKey.replace(
|
|
132
|
+
'EXTENDED_LIGHTING_AVAILABLE=false',
|
|
133
|
+
'EXTENDED_LIGHTING_AVAILABLE=true',
|
|
134
|
+
);
|
|
135
|
+
const wrongProjectorKey = goodKey.replace(
|
|
136
|
+
'PROJECTOR_AVAILABLE=false',
|
|
137
|
+
'PROJECTOR_AVAILABLE=true',
|
|
138
|
+
);
|
|
139
|
+
const wrongTransmissionKey = goodKey.replace(
|
|
140
|
+
'TRANSMISSION_AVAILABLE=false',
|
|
141
|
+
'TRANSMISSION_AVAILABLE=true',
|
|
142
|
+
);
|
|
143
|
+
const variant = (definesKey: string, defines: Record<string, boolean>) => ({
|
|
144
|
+
definesKey,
|
|
145
|
+
defines,
|
|
146
|
+
composedWgsl: definesKey,
|
|
147
|
+
});
|
|
148
|
+
const baseDefines = {
|
|
149
|
+
CLUSTER_FORWARD_AVAILABLE: true,
|
|
150
|
+
EXTENDED_LIGHTING_AVAILABLE: false,
|
|
151
|
+
PROBE_BLEND_AVAILABLE: true,
|
|
152
|
+
PROJECTOR_AVAILABLE: false,
|
|
153
|
+
STORAGE_BUFFER_AVAILABLE: true,
|
|
154
|
+
TRANSMISSION_AVAILABLE: false,
|
|
155
|
+
VERTEX_COLOR_AVAILABLE: true,
|
|
156
|
+
};
|
|
157
|
+
const selected = selectProbePrewarmVariants(
|
|
158
|
+
standardEntry([
|
|
159
|
+
variant(goodKey, baseDefines),
|
|
160
|
+
variant(wrongExtendedKey, { ...baseDefines, EXTENDED_LIGHTING_AVAILABLE: true }),
|
|
161
|
+
variant(wrongProjectorKey, { ...baseDefines, PROJECTOR_AVAILABLE: true }),
|
|
162
|
+
variant(wrongTransmissionKey, { ...baseDefines, TRANSMISSION_AVAILABLE: true }),
|
|
163
|
+
]),
|
|
164
|
+
true,
|
|
165
|
+
false,
|
|
166
|
+
false,
|
|
167
|
+
true,
|
|
168
|
+
false,
|
|
169
|
+
);
|
|
170
|
+
expect(selected.map((candidate) => candidate.definesKey)).toEqual([goodKey]);
|
|
161
171
|
});
|
|
162
172
|
});
|
|
@@ -219,7 +219,9 @@ describe('volumetric fog RenderGraph topology', () => {
|
|
|
219
219
|
fileURLToPath(new URL('../render-system.ts', import.meta.url)),
|
|
220
220
|
'utf8',
|
|
221
221
|
);
|
|
222
|
-
const recoverStart = renderSystemSource.indexOf(
|
|
222
|
+
const recoverStart = renderSystemSource.indexOf(
|
|
223
|
+
'resetForRecover(retiringPipelineState?: PipelineState, replacementDevice?: RhiDevice): void {',
|
|
224
|
+
);
|
|
223
225
|
expect(recoverStart).toBeGreaterThanOrEqual(0);
|
|
224
226
|
const recoverEnd = renderSystemSource.indexOf(
|
|
225
227
|
'restorePostProcessResources(): void',
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ImportTransport } from '@forgeax/engine-types';
|
|
2
|
+
|
|
3
|
+
/** Build-tool inputs forwarded from the host into renderer assembly. */
|
|
4
|
+
export interface BundlerOptions {
|
|
5
|
+
readonly importTransport?: ImportTransport | undefined;
|
|
6
|
+
readonly shaderManifestUrl?: string | undefined;
|
|
7
|
+
/** Exact checkout revision emitted by the build-tool adapter. */
|
|
8
|
+
readonly build?: string | undefined;
|
|
9
|
+
}
|
|
@@ -14,6 +14,14 @@ const COMPRESSION_FEATURES: GPUFeatureName[] = [
|
|
|
14
14
|
// request that larger limit when the adapter can provide it; adapter limits are
|
|
15
15
|
// not automatically inherited by requestDevice().
|
|
16
16
|
export const STANDARD_PBR_REQUIRED_SAMPLED_TEXTURES = 17;
|
|
17
|
+
/**
|
|
18
|
+
* The complete Standard physical root can declare all optional texture slots.
|
|
19
|
+
* Its material group therefore needs one more sampled-texture entry than the
|
|
20
|
+
* extended-lighting topology alone. Request this ceiling when the adapter can
|
|
21
|
+
* provide it; lower-capability devices remain fail-closed at material
|
|
22
|
+
* pipeline admission instead of receiving an invalid WebGPU layout.
|
|
23
|
+
*/
|
|
24
|
+
export const STANDARD_PHYSICAL_REQUIRED_SAMPLED_TEXTURES = 21;
|
|
17
25
|
|
|
18
26
|
export interface DeviceFeatureAdmissionOptions {
|
|
19
27
|
readonly gpuPassTiming?: object | undefined;
|
|
@@ -41,11 +49,13 @@ export function deriveDeviceFeatureAdmission(
|
|
|
41
49
|
}
|
|
42
50
|
const adapterSampledTextureLimit = adapter.limits?.maxSampledTexturesPerShaderStage ?? 0;
|
|
43
51
|
const requiredSampledTextureLimit =
|
|
44
|
-
adapterSampledTextureLimit >=
|
|
45
|
-
?
|
|
46
|
-
: adapterSampledTextureLimit >=
|
|
47
|
-
?
|
|
48
|
-
:
|
|
52
|
+
adapterSampledTextureLimit >= STANDARD_PHYSICAL_REQUIRED_SAMPLED_TEXTURES
|
|
53
|
+
? STANDARD_PHYSICAL_REQUIRED_SAMPLED_TEXTURES
|
|
54
|
+
: adapterSampledTextureLimit >= EXTENDED_LIGHTING_REQUIRED_SAMPLED_TEXTURES
|
|
55
|
+
? EXTENDED_LIGHTING_REQUIRED_SAMPLED_TEXTURES
|
|
56
|
+
: adapterSampledTextureLimit >= STANDARD_PBR_REQUIRED_SAMPLED_TEXTURES
|
|
57
|
+
? STANDARD_PBR_REQUIRED_SAMPLED_TEXTURES
|
|
58
|
+
: undefined;
|
|
49
59
|
return {
|
|
50
60
|
requiredFeatures,
|
|
51
61
|
...(requiredSampledTextureLimit === undefined
|