@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
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { resolveAssetHandle } from '@forgeax/engine-assets-runtime';
|
|
2
|
-
import type { World } from '@forgeax/engine-ecs';
|
|
3
2
|
import {
|
|
4
3
|
deriveTextureLayout,
|
|
5
4
|
type MaterialAsset,
|
|
@@ -11,6 +10,7 @@ import type {
|
|
|
11
10
|
MeshMaterialBindingPreparationFailure,
|
|
12
11
|
MeshMaterialBindingResidency,
|
|
13
12
|
} from './mesh-material-bindings';
|
|
13
|
+
import type { RenderResourceScope } from './publication/resource-scope';
|
|
14
14
|
import type { RenderSystemInternals } from './record/render-context';
|
|
15
15
|
import { materialSamplerHandles, materialTextureHandles } from './recovery/render-system-candidate';
|
|
16
16
|
import type { MaterialSnapshot } from './render-system-extract';
|
|
@@ -49,7 +49,7 @@ function preparationFailureFrom(error: unknown): MeshMaterialBindingPreparationF
|
|
|
49
49
|
* already resident resource remains last-known-good.
|
|
50
50
|
*/
|
|
51
51
|
export function observeMaterialResidency(
|
|
52
|
-
world:
|
|
52
|
+
world: RenderResourceScope | undefined,
|
|
53
53
|
material: MaterialSnapshot,
|
|
54
54
|
internals: RenderSystemInternals,
|
|
55
55
|
): MeshMaterialBindingResidency {
|
package/src/render-system.ts
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import { projectCaptureScene } from './capture/scene-projection';
|
|
2
|
+
import { renderMaterialContext } from './extract/material-context';
|
|
3
|
+
import { RenderPublicationError } from './publication/contract';
|
|
4
|
+
import { preparePublicationGeometry } from './publication/prepare-geometry';
|
|
5
|
+
import type { PreparedRenderPublication } from './publication/receiver';
|
|
6
|
+
import { type RenderResourceScope, renderTime } from './publication/resource-scope';
|
|
2
7
|
import type { RenderSceneBounds } from './scene/render-scene-types';
|
|
3
8
|
// @forgeax/engine-math is referenced through render-system-record.ts which builds
|
|
4
9
|
// view/proj matrices and worldFromLocal via `mat4.compose / .multiply /
|
|
@@ -6,13 +11,13 @@ import type { RenderSceneBounds } from './scene/render-scene-types';
|
|
|
6
11
|
// asserts `/@forgeax\/engine-math/` shows up in render-system.ts source).
|
|
7
12
|
|
|
8
13
|
import { numMipLevels } from '@forgeax/engine-assets-runtime';
|
|
9
|
-
import {
|
|
14
|
+
import type { World } from '@forgeax/engine-ecs';
|
|
10
15
|
import type { RenderReadLease } from '@forgeax/engine-ecs/projection';
|
|
11
16
|
import type { RecorderSession } from '@forgeax/engine-profiler';
|
|
12
17
|
import type { CompiledRenderGraphInfo } from '@forgeax/engine-render-graph';
|
|
13
18
|
import type { BindGroupLayout, Buffer, RenderPipeline, RhiDevice } from '@forgeax/engine-rhi';
|
|
14
19
|
import { err, ok, type Result, RhiError } from '@forgeax/engine-rhi';
|
|
15
|
-
import { type RenderPipelineAsset, toShared } from '@forgeax/engine-types';
|
|
20
|
+
import { type Handle, type RenderPipelineAsset, toShared } from '@forgeax/engine-types';
|
|
16
21
|
import {
|
|
17
22
|
type DirectionalShadowInspectionSource,
|
|
18
23
|
directionalShadowProfileFromQuality,
|
|
@@ -363,6 +368,7 @@ export interface RenderSystem {
|
|
|
363
368
|
opts: DrawOwnerOptions,
|
|
364
369
|
renderReadLeases?: readonly RenderReadLease[],
|
|
365
370
|
timingCapture?: GpuTimingCapture,
|
|
371
|
+
publication?: PreparedRenderPublication,
|
|
366
372
|
): boolean;
|
|
367
373
|
/**
|
|
368
374
|
* Return the asset binding consumed by the last successful record pass.
|
|
@@ -604,7 +610,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
604
610
|
);
|
|
605
611
|
let releaseProfilerCatalog =
|
|
606
612
|
phaseCatalogRegistration?.ok === true ? phaseCatalogRegistration.value : undefined;
|
|
607
|
-
let preparedWorlds: readonly
|
|
613
|
+
let preparedWorlds: readonly RenderResourceScope[] = [];
|
|
608
614
|
const resolveFeatureNoise = createFeatureNoiseResolver({
|
|
609
615
|
scope: internals.deviceScope,
|
|
610
616
|
getDevice: () => internals.device,
|
|
@@ -1497,7 +1503,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
1497
1503
|
let orderedDispatchCache:
|
|
1498
1504
|
| {
|
|
1499
1505
|
readonly source: readonly DispatchEntry[];
|
|
1500
|
-
readonly world:
|
|
1506
|
+
readonly world: RenderResourceScope;
|
|
1501
1507
|
readonly camera: readonly CameraSnapshot[];
|
|
1502
1508
|
readonly renderables: readonly RenderableSnapshot[];
|
|
1503
1509
|
readonly value: readonly DispatchEntry[];
|
|
@@ -1628,7 +1634,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
1628
1634
|
(
|
|
1629
1635
|
runtime: RenderSystemInternals,
|
|
1630
1636
|
gpuWork: RenderFeatureGpuWorkOwner,
|
|
1631
|
-
worlds: readonly
|
|
1637
|
+
worlds: readonly RenderResourceScope[],
|
|
1632
1638
|
caches: PreparedResolverCaches,
|
|
1633
1639
|
) =>
|
|
1634
1640
|
(input: RenderFeaturePreparedGraphicsResolverInput): PreparedGraphicsResolver => {
|
|
@@ -1845,7 +1851,6 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
1845
1851
|
) {
|
|
1846
1852
|
return preparedMaterialBindings(
|
|
1847
1853
|
runtime,
|
|
1848
|
-
caches,
|
|
1849
1854
|
worlds,
|
|
1850
1855
|
materialShaderId,
|
|
1851
1856
|
material.world,
|
|
@@ -2198,9 +2203,12 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2198
2203
|
opts: DrawOwnerOptions,
|
|
2199
2204
|
renderReadLeases?: readonly RenderReadLease[],
|
|
2200
2205
|
timingCapture?: GpuTimingCapture,
|
|
2206
|
+
publication?: PreparedRenderPublication,
|
|
2201
2207
|
): boolean {
|
|
2202
2208
|
const composition = canonicalizeWorldComposition(worlds, opts, renderReadLeases);
|
|
2203
|
-
const
|
|
2209
|
+
const sourceWorlds = composition.worlds;
|
|
2210
|
+
const compositionWorlds: readonly RenderResourceScope[] =
|
|
2211
|
+
publication === undefined ? sourceWorlds : [publication.resources];
|
|
2204
2212
|
const compositionLeases = composition.leases;
|
|
2205
2213
|
preparedWorlds = compositionWorlds;
|
|
2206
2214
|
const profileSession = internals.profiler?.activeSession();
|
|
@@ -2240,21 +2248,45 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2240
2248
|
// so a hot-swap cannot reuse passes compiled for the retired pipeline.
|
|
2241
2249
|
resetRenderFeatureGraphState(internals);
|
|
2242
2250
|
lastBuiltPipelineHandle = frameState.installedPipelineHandle;
|
|
2243
|
-
persistentRenderScene.invalidate();
|
|
2251
|
+
if (publication === undefined) persistentRenderScene.invalidate();
|
|
2244
2252
|
}
|
|
2245
2253
|
dispatchCounts.unlit = 0;
|
|
2246
2254
|
|
|
2247
|
-
const resourceWorld = compositionWorlds[resourceOwner] as
|
|
2255
|
+
const resourceWorld = compositionWorlds[resourceOwner] as RenderResourceScope;
|
|
2248
2256
|
let frame: ReturnType<PersistentRenderScene['extractComposition']>;
|
|
2249
2257
|
try {
|
|
2250
2258
|
frame = runProfiledRenderPhase(profileSession, 'extract', () => {
|
|
2259
|
+
if (publication !== undefined) {
|
|
2260
|
+
for (const handle of [
|
|
2261
|
+
...publication.packet.invalidatedAssets,
|
|
2262
|
+
...publication.packet.retiredAssets,
|
|
2263
|
+
]) {
|
|
2264
|
+
internals.gpuStore.invalidateMesh(handle, publication.resources);
|
|
2265
|
+
internals.gpuStore.evictTexture(
|
|
2266
|
+
handle as Handle<'TextureAsset', 'shared'>,
|
|
2267
|
+
publication.resources,
|
|
2268
|
+
);
|
|
2269
|
+
}
|
|
2270
|
+
return persistentRenderScene.consumePublication(
|
|
2271
|
+
preparePublicationGeometry(
|
|
2272
|
+
publication,
|
|
2273
|
+
persistentRenderScene,
|
|
2274
|
+
internals.getPipelineState()?.skinPaletteAllocator,
|
|
2275
|
+
internals.assets,
|
|
2276
|
+
instanceCollections,
|
|
2277
|
+
internals.device.caps.storageBuffer
|
|
2278
|
+
? internals.getMaterialShaderArtifact
|
|
2279
|
+
: undefined,
|
|
2280
|
+
),
|
|
2281
|
+
);
|
|
2282
|
+
}
|
|
2251
2283
|
return persistentRenderScene.extractComposition(
|
|
2252
|
-
|
|
2284
|
+
sourceWorlds,
|
|
2253
2285
|
{ cameraOwner, resourceOwner },
|
|
2254
2286
|
internals.assets.catalogEpoch,
|
|
2255
2287
|
(renderables) =>
|
|
2256
2288
|
extractFrames(
|
|
2257
|
-
|
|
2289
|
+
sourceWorlds,
|
|
2258
2290
|
{
|
|
2259
2291
|
cameraOwner,
|
|
2260
2292
|
resourceOwner,
|
|
@@ -2264,25 +2296,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2264
2296
|
internals.getPipelineState(),
|
|
2265
2297
|
persistentRenderScene.materialSnapshotCacheStore(),
|
|
2266
2298
|
{
|
|
2267
|
-
...(internals.device.caps
|
|
2268
|
-
? {}
|
|
2269
|
-
: {
|
|
2270
|
-
materialContext: {
|
|
2271
|
-
backend:
|
|
2272
|
-
internals.device.caps.backendKind === 'wgpu-webgl2'
|
|
2273
|
-
? ('webgl2' as const)
|
|
2274
|
-
: internals.device.caps.backendKind,
|
|
2275
|
-
capability: internals.device.caps.storageBuffer
|
|
2276
|
-
? ('storage-buffer' as const)
|
|
2277
|
-
: ('uniform-fallback' as const),
|
|
2278
|
-
pipeline: 'forward' as const,
|
|
2279
|
-
geometry: 'mesh' as const,
|
|
2280
|
-
pass: 'forward' as const,
|
|
2281
|
-
profile: 'forgeax-material-wgsl-v1' as const,
|
|
2282
|
-
toolchain: 'naga-oil' as const,
|
|
2283
|
-
instrumentation: 'none' as const,
|
|
2284
|
-
},
|
|
2285
|
-
}),
|
|
2299
|
+
...renderMaterialContext(internals.device.caps),
|
|
2286
2300
|
cull: 'none',
|
|
2287
2301
|
retainHidden: true,
|
|
2288
2302
|
renderables,
|
|
@@ -2308,6 +2322,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2308
2322
|
lastMotionBlurInvalidParams = undefined;
|
|
2309
2323
|
const {
|
|
2310
2324
|
cameras: extractedCameras,
|
|
2325
|
+
auxiliaryCameras,
|
|
2311
2326
|
cubeCameras,
|
|
2312
2327
|
lights,
|
|
2313
2328
|
environment,
|
|
@@ -2333,7 +2348,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2333
2348
|
frameState,
|
|
2334
2349
|
internals,
|
|
2335
2350
|
cameras[0],
|
|
2336
|
-
compositionWorlds[cameraOwner] as
|
|
2351
|
+
compositionWorlds[cameraOwner] as RenderResourceScope,
|
|
2337
2352
|
);
|
|
2338
2353
|
if (!preparedOutput.ok) {
|
|
2339
2354
|
internals.errorRegistry.fire(preparedOutput.error);
|
|
@@ -2814,7 +2829,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2814
2829
|
const motionBlurParams = cameras[0]?.motionBlur;
|
|
2815
2830
|
let motionBlurDelta = 0;
|
|
2816
2831
|
try {
|
|
2817
|
-
const delta = (compositionWorlds[cameraOwner] as
|
|
2832
|
+
const delta = renderTime(compositionWorlds[cameraOwner] as RenderResourceScope).delta;
|
|
2818
2833
|
motionBlurDelta = Number.isFinite(delta) ? Math.max(0, delta) : 0;
|
|
2819
2834
|
} catch {
|
|
2820
2835
|
motionBlurDelta = 0;
|
|
@@ -2856,9 +2871,29 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2856
2871
|
.skylightResources;
|
|
2857
2872
|
let featureGraphCandidate: RenderFeatureGraphCandidate | undefined;
|
|
2858
2873
|
const preparedResourceBatches = runProfiledRenderPhase(profileSession, 'features', () => {
|
|
2874
|
+
if (
|
|
2875
|
+
publication?.packet.features.some(
|
|
2876
|
+
(row) =>
|
|
2877
|
+
!internals.featureHost?.features.some(
|
|
2878
|
+
(feature) => feature.identity === row.identity,
|
|
2879
|
+
),
|
|
2880
|
+
)
|
|
2881
|
+
)
|
|
2882
|
+
throw new RenderPublicationError({
|
|
2883
|
+
reason: 'shape',
|
|
2884
|
+
subject: 'published feature has no receiver implementation',
|
|
2885
|
+
});
|
|
2859
2886
|
if (internals.featureHost === undefined) return [];
|
|
2860
2887
|
const featureFrame = runRenderFeatureFrame(internals.featureHost, {
|
|
2861
|
-
worlds:
|
|
2888
|
+
worlds: sourceWorlds,
|
|
2889
|
+
...(publication === undefined
|
|
2890
|
+
? {}
|
|
2891
|
+
: {
|
|
2892
|
+
publishedFeatures: publication.packet.features,
|
|
2893
|
+
...(publication.onFeatureSourceSubmitted === undefined
|
|
2894
|
+
? {}
|
|
2895
|
+
: { onFeatureSourceSubmitted: publication.onFeatureSourceSubmitted }),
|
|
2896
|
+
}),
|
|
2862
2897
|
owner: resourceOwner,
|
|
2863
2898
|
frameNumber: frameState.frameNumber,
|
|
2864
2899
|
...(cameras[0] === undefined ? {} : { selectedCamera: cameras[0] }),
|
|
@@ -3053,8 +3088,8 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3053
3088
|
frameState.standardLutState.resident !== null ||
|
|
3054
3089
|
frameState.pendingStandardLutState !== undefined;
|
|
3055
3090
|
if (hasLiveFeatureState) {
|
|
3056
|
-
const cameraWorld = compositionWorlds[cameraOwner] as
|
|
3057
|
-
const deltaTime = cameraWorld
|
|
3091
|
+
const cameraWorld = compositionWorlds[cameraOwner] as RenderResourceScope;
|
|
3092
|
+
const deltaTime = renderTime(cameraWorld).delta;
|
|
3058
3093
|
stageLiveFeatureState(
|
|
3059
3094
|
cameras[0],
|
|
3060
3095
|
Number.isFinite(deltaTime) ? Math.max(0, deltaTime) : 0,
|
|
@@ -3071,16 +3106,15 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3071
3106
|
frameState.surfaceSubmissionObservation = surfaceSubmissionCandidate;
|
|
3072
3107
|
const probeCaptureScene =
|
|
3073
3108
|
shadowCasterProjection !== undefined &&
|
|
3074
|
-
|
|
3109
|
+
(auxiliaryCameras.length > 0 ||
|
|
3110
|
+
cubeCameras.length > 0 ||
|
|
3111
|
+
reflectionProbeRecord.graph.work.some((work) => work.rawCaptureFace !== undefined))
|
|
3075
3112
|
? projectCaptureScene(shadowCasterProjection, submissionRenderables, orderedDispatch)
|
|
3076
3113
|
: undefined;
|
|
3077
|
-
//
|
|
3078
|
-
// draws. It lets the presentation fact distinguish a clear/submit
|
|
3079
|
-
// from a frame where geometry or its pipeline was skipped, without
|
|
3080
|
-
// retaining a second readiness registry or per-asset counter.
|
|
3114
|
+
// Track actual draws so a clear/submit cannot claim visible geometry was presented.
|
|
3081
3115
|
const presentedRenderableKeys = new Set<number>();
|
|
3082
3116
|
const presentedSubmeshKeys = new Set<string>();
|
|
3083
|
-
const consumeDynamicGeometry = dynamicGeometryFrames.onRenderableDraw(
|
|
3117
|
+
const consumeDynamicGeometry = dynamicGeometryFrames.onRenderableDraw(sourceWorlds);
|
|
3084
3118
|
const markPresentedRenderable = (
|
|
3085
3119
|
entry: Parameters<typeof consumeDynamicGeometry>[0],
|
|
3086
3120
|
submeshIndex?: number,
|
|
@@ -3131,7 +3165,9 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3131
3165
|
},
|
|
3132
3166
|
...(occlusionProjection === undefined ? {} : { occlusion: occlusionProjection }),
|
|
3133
3167
|
frameTime: (() => {
|
|
3134
|
-
const elapsed = (
|
|
3168
|
+
const elapsed = renderTime(
|
|
3169
|
+
compositionWorlds[cameraOwner] as RenderResourceScope,
|
|
3170
|
+
).elapsed;
|
|
3135
3171
|
return Number.isFinite(elapsed) ? elapsed : 0;
|
|
3136
3172
|
})(),
|
|
3137
3173
|
deviceGeneration: internals.deviceScope.generation,
|
|
@@ -3145,6 +3181,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3145
3181
|
pointsLinesOwner,
|
|
3146
3182
|
{
|
|
3147
3183
|
snapshots: cubeCameras,
|
|
3184
|
+
auxiliaryCameras,
|
|
3148
3185
|
scheduler: cubeCaptureScheduler,
|
|
3149
3186
|
state: cubeCaptureState,
|
|
3150
3187
|
reflectionProbes: reflectionProbeRecord,
|
|
@@ -3329,7 +3366,9 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3329
3366
|
width: Math.max(1, internals.canvas.width),
|
|
3330
3367
|
height: Math.max(1, internals.canvas.height),
|
|
3331
3368
|
frameTime: (() => {
|
|
3332
|
-
const elapsed = (
|
|
3369
|
+
const elapsed = renderTime(
|
|
3370
|
+
compositionWorlds[cameraOwner] as RenderResourceScope,
|
|
3371
|
+
).elapsed;
|
|
3333
3372
|
return Number.isFinite(elapsed) ? elapsed : 0;
|
|
3334
3373
|
})(),
|
|
3335
3374
|
...(surfaceDynamicInputFrame === undefined
|
|
@@ -4054,14 +4093,3 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
4054
4093
|
export function resolveInspectionBuild(internals: Pick<RenderSystemInternals, 'build'>): string {
|
|
4055
4094
|
return internals.build ?? 'render-system';
|
|
4056
4095
|
}
|
|
4057
|
-
|
|
4058
|
-
// @forgeax/engine-render - built-in record context extension.
|
|
4059
|
-
//
|
|
4060
|
-
// The public RenderPipelineContext is canonical in render-contract.ts. This
|
|
4061
|
-
// owner adds only concrete assembly state for built-in record closures.
|
|
4062
|
-
|
|
4063
|
-
/**
|
|
4064
|
-
* Package-private extension consumed by the built-in record closures only.
|
|
4065
|
-
* Custom pipeline authors see the leaf RenderPipelineContext contract and
|
|
4066
|
-
* never this surface.
|
|
4067
|
-
*/
|
|
@@ -1,29 +1,17 @@
|
|
|
1
1
|
import { RuntimeMaterialValue, RuntimeMeshVertices } from '@forgeax/engine-assets-runtime';
|
|
2
|
-
import type { EntityHandle,
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
type StateProjectionBatch,
|
|
2
|
+
import type { EntityHandle, World } from '@forgeax/engine-ecs';
|
|
3
|
+
import type {
|
|
4
|
+
RenderReadLease,
|
|
5
|
+
RenderReadVersion,
|
|
6
|
+
StateProjection,
|
|
7
|
+
StateProjectionBatch,
|
|
9
8
|
} from '@forgeax/engine-ecs/projection';
|
|
10
9
|
import { box3, frustum, mat4 } from '@forgeax/engine-math';
|
|
11
10
|
import { type RhiDevice, RhiError } from '@forgeax/engine-rhi';
|
|
12
|
-
import { ChildOf, Children, GlobalTransform, MorphWeights
|
|
11
|
+
import { ChildOf, Children, GlobalTransform, MorphWeights } from '@forgeax/engine-scene';
|
|
13
12
|
import { Skin } from '@forgeax/engine-skinning';
|
|
14
13
|
import { err, ok, type Result } from '@forgeax/engine-types';
|
|
15
|
-
import {
|
|
16
|
-
Instances,
|
|
17
|
-
Layer,
|
|
18
|
-
Lines,
|
|
19
|
-
MeshFilter,
|
|
20
|
-
MeshRenderer,
|
|
21
|
-
Points,
|
|
22
|
-
SortKey,
|
|
23
|
-
SpriteInstances,
|
|
24
|
-
SpriteRegionOverride,
|
|
25
|
-
Visibility,
|
|
26
|
-
} from '../components';
|
|
14
|
+
import { Instances, Lines, Points, SpriteInstances, Visibility } from '../components';
|
|
27
15
|
import type { DeviceScope, LifecycleResourceSpec } from '../device/device-scope';
|
|
28
16
|
import { gpuDrivenShadowDrawKey } from '../extract/gpu-driven';
|
|
29
17
|
import { motionBlurTemporalDemand } from '../features/motion-blur/motion-blur-params';
|
|
@@ -41,6 +29,8 @@ import type { InstanceProjectionStore } from '../instances';
|
|
|
41
29
|
import { fingerprintNumericArray, InstanceBoundsCache } from '../instances-derived-bounds';
|
|
42
30
|
import type { PointsLinesInspection } from '../points-lines/inspection';
|
|
43
31
|
import type { PointsLinesRetainedSnapshot } from '../points-lines/snapshot';
|
|
32
|
+
import type { PreparedRenderPublication } from '../publication/receiver';
|
|
33
|
+
import type { RenderResourceScope } from '../publication/resource-scope';
|
|
44
34
|
import { worldEntityKey } from '../record/frame-snapshot';
|
|
45
35
|
import {
|
|
46
36
|
type ReflectionProbeFact,
|
|
@@ -76,6 +66,13 @@ import type {
|
|
|
76
66
|
RenderSceneResyncReason,
|
|
77
67
|
RenderSceneSlot,
|
|
78
68
|
} from './render-scene-types';
|
|
69
|
+
import {
|
|
70
|
+
createGlobalTransformChangeQuery,
|
|
71
|
+
createRenderSourceState,
|
|
72
|
+
type GlobalTransformChangeQuery,
|
|
73
|
+
isRenderableMember,
|
|
74
|
+
RENDERABLE_SOURCE_COMPONENTS,
|
|
75
|
+
} from './render-source';
|
|
79
76
|
import { buildShadowFrusta } from './shadow-visibility';
|
|
80
77
|
import { createVisibilityBudget, type VisibilityBudget } from './visibility/budget';
|
|
81
78
|
import {
|
|
@@ -118,8 +115,6 @@ interface WorldTransformSpan {
|
|
|
118
115
|
readonly worlds: Readonly<Float32Array>;
|
|
119
116
|
}
|
|
120
117
|
|
|
121
|
-
type GlobalTransformChangeQuery = Query<readonly [typeof GlobalTransform]>;
|
|
122
|
-
|
|
123
118
|
function sameInstanceIdentitySet(
|
|
124
119
|
current: Uint32Array | undefined,
|
|
125
120
|
previous: Uint32Array | undefined,
|
|
@@ -1151,7 +1146,7 @@ type PersistentGpuSceneInspection = PersistentRenderSceneInspection['gpu'];
|
|
|
1151
1146
|
|
|
1152
1147
|
interface PersistentCompositionEntry {
|
|
1153
1148
|
readonly token: object;
|
|
1154
|
-
readonly worlds: readonly
|
|
1149
|
+
readonly worlds: readonly RenderResourceScope[];
|
|
1155
1150
|
readonly projection: RenderScene;
|
|
1156
1151
|
readonly topology: BatchTopology;
|
|
1157
1152
|
readonly transmissionDemand: PersistentTransmissionDemandProjection;
|
|
@@ -1187,73 +1182,6 @@ interface PersistentCompositionEntry {
|
|
|
1187
1182
|
gpuDrivenSceneRequired: boolean;
|
|
1188
1183
|
}
|
|
1189
1184
|
|
|
1190
|
-
// Retained geometry consumes these component changes. Camera, lighting and
|
|
1191
|
-
// environment facts are freshly extracted by deriveFramePlan on every draw;
|
|
1192
|
-
// their edits must not recreate unrelated geometry or its submission history.
|
|
1193
|
-
const RENDERABLE_SOURCE_COMPONENTS = [
|
|
1194
|
-
ChildOf,
|
|
1195
|
-
MeshFilter,
|
|
1196
|
-
MeshRenderer,
|
|
1197
|
-
Instances,
|
|
1198
|
-
SpriteInstances,
|
|
1199
|
-
SpriteRegionOverride,
|
|
1200
|
-
Skin,
|
|
1201
|
-
Layer,
|
|
1202
|
-
Visibility,
|
|
1203
|
-
MorphWeights,
|
|
1204
|
-
Points,
|
|
1205
|
-
Lines,
|
|
1206
|
-
SortKey,
|
|
1207
|
-
] as const;
|
|
1208
|
-
function createGlobalTransformChangeQuery(world: World): GlobalTransformChangeQuery {
|
|
1209
|
-
const result = world.query({ read: [GlobalTransform], changed: [GlobalTransform] });
|
|
1210
|
-
if (!result.ok) throw result.error;
|
|
1211
|
-
const query = result.value as GlobalTransformChangeQuery;
|
|
1212
|
-
for (const _span of query.spans().unwrap()) {
|
|
1213
|
-
// The full rebuild consumed these values; establish the observation baseline.
|
|
1214
|
-
}
|
|
1215
|
-
return query;
|
|
1216
|
-
}
|
|
1217
|
-
|
|
1218
|
-
function createRenderSourceState(world: World) {
|
|
1219
|
-
// Numerical poses already have one span reader. Keep their table membership
|
|
1220
|
-
// in this projection, without scanning their changed rows a second time.
|
|
1221
|
-
const components = [...RENDERABLE_SOURCE_COMPONENTS, RuntimeMaterialValue, RuntimeMeshVertices];
|
|
1222
|
-
const projection = createStateProjection(world, components, [
|
|
1223
|
-
...components,
|
|
1224
|
-
Transform,
|
|
1225
|
-
GlobalTransform,
|
|
1226
|
-
]);
|
|
1227
|
-
const entities = new Map<number, EntityHandle>();
|
|
1228
|
-
const contentHandles = new Map<number, readonly number[]>();
|
|
1229
|
-
const batch = projection.read();
|
|
1230
|
-
for (const index of batch.indices) {
|
|
1231
|
-
const entity = projection.entity(index);
|
|
1232
|
-
if (entity !== undefined) {
|
|
1233
|
-
entities.set(index, entity);
|
|
1234
|
-
const handles: number[] = [];
|
|
1235
|
-
const material = world.hasComponent(entity, RuntimeMaterialValue)
|
|
1236
|
-
? world.get(entity, RuntimeMaterialValue)
|
|
1237
|
-
: undefined;
|
|
1238
|
-
const mesh = world.hasComponent(entity, RuntimeMeshVertices)
|
|
1239
|
-
? world.get(entity, RuntimeMeshVertices)
|
|
1240
|
-
: undefined;
|
|
1241
|
-
if (material?.ok) handles.push(Number(material.value.asset));
|
|
1242
|
-
if (mesh?.ok) handles.push(Number(mesh.value.asset));
|
|
1243
|
-
if (handles.length > 0) contentHandles.set(index, handles);
|
|
1244
|
-
}
|
|
1245
|
-
}
|
|
1246
|
-
return { projection, entities, contentHandles, batch };
|
|
1247
|
-
}
|
|
1248
|
-
|
|
1249
|
-
function isRenderableMember(world: World, entity: number): boolean {
|
|
1250
|
-
return (
|
|
1251
|
-
world.hasComponent(entity as EntityHandle, MeshRenderer) &&
|
|
1252
|
-
world.hasComponent(entity as EntityHandle, Transform) &&
|
|
1253
|
-
world.hasComponent(entity as EntityHandle, MeshFilter)
|
|
1254
|
-
);
|
|
1255
|
-
}
|
|
1256
|
-
|
|
1257
1185
|
function sourceMembershipChanged(world: World, slot: RenderSceneSlot): boolean {
|
|
1258
1186
|
const entity = slot.entityKey as EntityHandle;
|
|
1259
1187
|
const snapshot = slot.snapshot;
|
|
@@ -1608,7 +1536,7 @@ export class PersistentRenderScene {
|
|
|
1608
1536
|
return this.visibilityBudget;
|
|
1609
1537
|
}
|
|
1610
1538
|
|
|
1611
|
-
private visibilityWorldKey(world:
|
|
1539
|
+
private visibilityWorldKey(world: RenderResourceScope | undefined, fallback: number): number {
|
|
1612
1540
|
if (world === undefined) return fallback;
|
|
1613
1541
|
const existing = this.visibilityWorldKeys.get(world.identity);
|
|
1614
1542
|
if (existing !== undefined) return existing;
|
|
@@ -1618,12 +1546,12 @@ export class PersistentRenderScene {
|
|
|
1618
1546
|
return key;
|
|
1619
1547
|
}
|
|
1620
1548
|
|
|
1621
|
-
private worldKeyAt(worlds: readonly
|
|
1549
|
+
private worldKeyAt(worlds: readonly RenderResourceScope[], worldId: number): number {
|
|
1622
1550
|
return this.visibilityWorldKey(worlds[worldId], worldId);
|
|
1623
1551
|
}
|
|
1624
1552
|
|
|
1625
1553
|
/** Stable World routing keys for the current worlds[] frame projection. */
|
|
1626
|
-
visibilityWorldKeysFor(worlds: readonly
|
|
1554
|
+
visibilityWorldKeysFor(worlds: readonly RenderResourceScope[]): readonly number[] {
|
|
1627
1555
|
return worlds.map((world, worldId) => this.visibilityWorldKey(world, worldId));
|
|
1628
1556
|
}
|
|
1629
1557
|
|
|
@@ -1632,6 +1560,10 @@ export class PersistentRenderScene {
|
|
|
1632
1560
|
return this.composition?.projection.slotsSnapshot() ?? [];
|
|
1633
1561
|
}
|
|
1634
1562
|
|
|
1563
|
+
compositionSlot(worldId: number, entityKey: number): RenderSceneSlot | undefined {
|
|
1564
|
+
return this.composition?.projection.slot(worldId, entityKey);
|
|
1565
|
+
}
|
|
1566
|
+
|
|
1635
1567
|
shadowCasterProjection(): PersistentShadowCasterProjection | undefined {
|
|
1636
1568
|
return this.shadowProjection;
|
|
1637
1569
|
}
|
|
@@ -1642,7 +1574,7 @@ export class PersistentRenderScene {
|
|
|
1642
1574
|
}
|
|
1643
1575
|
|
|
1644
1576
|
private stableEntityKey(
|
|
1645
|
-
worlds: readonly
|
|
1577
|
+
worlds: readonly RenderResourceScope[],
|
|
1646
1578
|
renderable: Pick<RenderableSnapshot, 'worldId' | 'entityKey'>,
|
|
1647
1579
|
): number {
|
|
1648
1580
|
return worldEntityKey(this.worldKeyAt(worlds, renderable.worldId), renderable.entityKey);
|
|
@@ -1650,7 +1582,7 @@ export class PersistentRenderScene {
|
|
|
1650
1582
|
|
|
1651
1583
|
/** Feed the facet from extracted renderables using persistent slot identity. */
|
|
1652
1584
|
updateVisibilityFacet(
|
|
1653
|
-
worlds: readonly
|
|
1585
|
+
worlds: readonly RenderResourceScope[],
|
|
1654
1586
|
camera: CameraSnapshot | undefined,
|
|
1655
1587
|
renderables: readonly RenderableSnapshot[],
|
|
1656
1588
|
): void {
|
|
@@ -1710,7 +1642,7 @@ export class PersistentRenderScene {
|
|
|
1710
1642
|
* visible through `decideVisibility`.
|
|
1711
1643
|
*/
|
|
1712
1644
|
projectVisibility(
|
|
1713
|
-
worlds: readonly
|
|
1645
|
+
worlds: readonly RenderResourceScope[],
|
|
1714
1646
|
camera: CameraSnapshot | undefined,
|
|
1715
1647
|
renderables: readonly RenderableSnapshot[],
|
|
1716
1648
|
dispatch: readonly DispatchEntry[],
|
|
@@ -1884,6 +1816,77 @@ export class PersistentRenderScene {
|
|
|
1884
1816
|
return this.reflectionProbes.snapshot();
|
|
1885
1817
|
}
|
|
1886
1818
|
|
|
1819
|
+
consumePublication(input: PreparedRenderPublication): ExtractedFrame {
|
|
1820
|
+
const { resources, packet, frame } = input;
|
|
1821
|
+
let entry = this.composition;
|
|
1822
|
+
if (entry === undefined || packet.baseline) {
|
|
1823
|
+
this.invalidate();
|
|
1824
|
+
const projection = new RenderScene();
|
|
1825
|
+
entry = {
|
|
1826
|
+
token: {},
|
|
1827
|
+
worlds: [resources],
|
|
1828
|
+
projection,
|
|
1829
|
+
topology: new BatchTopology(),
|
|
1830
|
+
transmissionDemand: new PersistentTransmissionDemandProjection(),
|
|
1831
|
+
hiddenEntityReports: [],
|
|
1832
|
+
worldKeys: this.visibilityWorldKeysFor([resources]),
|
|
1833
|
+
readVersions: [],
|
|
1834
|
+
leaseIdentities: [],
|
|
1835
|
+
transformQueries: [],
|
|
1836
|
+
sourceStates: [],
|
|
1837
|
+
dispatchBySlot: new Map(),
|
|
1838
|
+
dispatchRevision: 0,
|
|
1839
|
+
dispatchCache: undefined,
|
|
1840
|
+
skinConsumersByJoint: new Map(),
|
|
1841
|
+
pendingRenderableEntitiesByWorld: [],
|
|
1842
|
+
unavailableSlots: new Set(),
|
|
1843
|
+
catalogEpoch: 0,
|
|
1844
|
+
probeProjection: new ProbeBlendSceneProjection(),
|
|
1845
|
+
probeObjects: undefined,
|
|
1846
|
+
temporalDemanded: false,
|
|
1847
|
+
gpuDrivenSceneRequired: true,
|
|
1848
|
+
};
|
|
1849
|
+
this.composition = entry;
|
|
1850
|
+
this.fullRebuilds++;
|
|
1851
|
+
this.lastResyncReason = 'attach';
|
|
1852
|
+
}
|
|
1853
|
+
this.worldEntitiesScanned = 0;
|
|
1854
|
+
this.sceneTableUploadBytes = 0;
|
|
1855
|
+
const removedDemand: TransmissionDemandOperation[] = [];
|
|
1856
|
+
for (const operation of input.operations) {
|
|
1857
|
+
if (operation.kind !== 'remove' && operation.snapshot === undefined) continue;
|
|
1858
|
+
const previous = entry.projection.slot(0, operation.entityKey);
|
|
1859
|
+
for (let index = 0; index < (previous?.snapshot.materials.length ?? 0); index++)
|
|
1860
|
+
removedDemand.push({ kind: 'remove', key: `0:${operation.entityKey}:${index}` });
|
|
1861
|
+
}
|
|
1862
|
+
const delta = entry.projection.apply(input.operations);
|
|
1863
|
+
for (const removed of delta.removedSlots) {
|
|
1864
|
+
entry.dispatchBySlot.delete(removed.slot);
|
|
1865
|
+
this.stableSlotByEntity.delete(worldEntityKey(entry.worldKeys[0] ?? 0, removed.entityKey));
|
|
1866
|
+
}
|
|
1867
|
+
for (const recreated of delta.recreatedSlots) entry.dispatchBySlot.delete(recreated.slot);
|
|
1868
|
+
for (const [slot, dispatch] of dispatchEntriesBySlot(frame, entry.projection))
|
|
1869
|
+
entry.dispatchBySlot.set(slot, dispatch);
|
|
1870
|
+
if (frame.renderables.length || packet.removed.length) {
|
|
1871
|
+
entry.dispatchRevision++;
|
|
1872
|
+
entry.dispatchCache = undefined;
|
|
1873
|
+
this.visibilityFacets.clear();
|
|
1874
|
+
this.invalidateActiveEntityRevision();
|
|
1875
|
+
}
|
|
1876
|
+
for (const slot of [...delta.createdSlots, ...delta.updatedSlots, ...delta.recreatedSlots])
|
|
1877
|
+
this.stableSlotByEntity.set(worldEntityKey(entry.worldKeys[0] ?? 0, slot.entityKey), slot);
|
|
1878
|
+
entry.transmissionDemand.apply([
|
|
1879
|
+
...removedDemand,
|
|
1880
|
+
...transmissionDemandOperations(frame.renderables),
|
|
1881
|
+
]);
|
|
1882
|
+
entry.topology.apply(delta);
|
|
1883
|
+
this.syncGpuOwner(entry.token, entry.projection, delta);
|
|
1884
|
+
if (input.operations.length) this.deltaFrames++;
|
|
1885
|
+
else this.noChangeFrames++;
|
|
1886
|
+
this.transformUpdates += delta.updated;
|
|
1887
|
+
return this.deriveFramePlan(entry, frame);
|
|
1888
|
+
}
|
|
1889
|
+
|
|
1887
1890
|
extractComposition(
|
|
1888
1891
|
worlds: readonly World[],
|
|
1889
1892
|
owner: { readonly cameraOwner: number; readonly resourceOwner: number },
|
|
@@ -1897,7 +1900,7 @@ export class PersistentRenderScene {
|
|
|
1897
1900
|
const sameWorldSet =
|
|
1898
1901
|
entry !== undefined &&
|
|
1899
1902
|
entry.worlds.length === worlds.length &&
|
|
1900
|
-
entry.worlds.every((world) => worlds.
|
|
1903
|
+
entry.worlds.every((world) => worlds.some((local) => local === world));
|
|
1901
1904
|
const worldOrderChanged =
|
|
1902
1905
|
entry !== undefined &&
|
|
1903
1906
|
sameWorldSet &&
|
|
@@ -2708,7 +2711,7 @@ export class PersistentRenderScene {
|
|
|
2708
2711
|
preserveVisibilityOnReorder = false,
|
|
2709
2712
|
): ExtractedFrame {
|
|
2710
2713
|
const previousEntry = this.composition;
|
|
2711
|
-
const sourceStates = worlds.map(createRenderSourceState);
|
|
2714
|
+
const sourceStates = worlds.map((world) => createRenderSourceState(world));
|
|
2712
2715
|
const candidateFrame = buildCandidateFrame({
|
|
2713
2716
|
kind: 'partial',
|
|
2714
2717
|
entitiesByWorld: sourceStates.map((source) => new Set(source.entities.values())),
|
|
@@ -2745,7 +2748,11 @@ export class PersistentRenderScene {
|
|
|
2745
2748
|
const renderables = candidateFrame.renderables;
|
|
2746
2749
|
const projection = previousEntry?.projection ?? new RenderScene();
|
|
2747
2750
|
if (previousEntry !== undefined) {
|
|
2748
|
-
projection.remapWorlds(
|
|
2751
|
+
projection.remapWorlds(
|
|
2752
|
+
previousEntry.worlds.map((world) =>
|
|
2753
|
+
(worlds as readonly RenderResourceScope[]).indexOf(world),
|
|
2754
|
+
),
|
|
2755
|
+
);
|
|
2749
2756
|
}
|
|
2750
2757
|
const desired = new Set(
|
|
2751
2758
|
renderables.map((snapshot) => identityKey(snapshot.worldId, snapshot.entityKey)),
|
|
@@ -2895,7 +2902,10 @@ export class PersistentRenderScene {
|
|
|
2895
2902
|
const candidateFrame: ExtractedFrame = {
|
|
2896
2903
|
...resourceFrame,
|
|
2897
2904
|
hiddenEntityReports: entry.hiddenEntityReports,
|
|
2898
|
-
visibilityStats:
|
|
2905
|
+
visibilityStats:
|
|
2906
|
+
entry.sourceStates.length === 0
|
|
2907
|
+
? resourceFrame.visibilityStats
|
|
2908
|
+
: { explicitlyHidden: entry.hiddenEntityReports.length },
|
|
2899
2909
|
dispatch,
|
|
2900
2910
|
};
|
|
2901
2911
|
entry.temporalDemanded = frameDemandsTemporal(candidateFrame);
|