@forgeax/engine-render 0.1.32 → 0.1.33
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 +379 -33
- package/dist/assembly/analytic-fog-registration.d.ts +3 -0
- package/dist/assembly/analytic-fog-registration.d.ts.map +1 -0
- package/dist/assembly/fxaa-registration.d.ts +4 -0
- package/dist/assembly/fxaa-registration.d.ts.map +1 -0
- package/dist/assembly/lod-observation.d.ts +4 -0
- package/dist/assembly/lod-observation.d.ts.map +1 -0
- package/dist/assembly/motion-blur-registration.d.ts +3 -0
- package/dist/assembly/motion-blur-registration.d.ts.map +1 -0
- package/dist/assembly/renderer-facade.d.ts.map +1 -1
- package/dist/assembly/temporal-post-process-prewarm.d.ts +13 -0
- package/dist/assembly/temporal-post-process-prewarm.d.ts.map +1 -0
- package/dist/assembly/webgpu-ready-contract.d.ts +4 -3
- package/dist/assembly/webgpu-ready-contract.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/bloom-admission.d.ts +13 -0
- package/dist/bloom-admission.d.ts.map +1 -0
- package/dist/{chunk-DRR7D3KX.mjs → chunk-3RTCJTH4.mjs} +12 -9
- package/dist/chunk-3RTCJTH4.mjs.map +1 -0
- package/dist/{chunk-S665NJNF.mjs → chunk-LEAXOMYJ.mjs} +3 -3
- package/dist/{chunk-S665NJNF.mjs.map → chunk-LEAXOMYJ.mjs.map} +1 -1
- package/dist/{chunk-6TFBXLRJ.mjs → chunk-NB2S7ZRX.mjs} +155 -11
- package/dist/chunk-NB2S7ZRX.mjs.map +1 -0
- package/dist/{chunk-LULCA3OF.mjs → chunk-NNQL7CB3.mjs} +4 -4
- package/dist/{chunk-LULCA3OF.mjs.map → chunk-NNQL7CB3.mjs.map} +1 -1
- package/dist/{chunk-4NNZQCL3.mjs → chunk-OO3DRYK7.mjs} +66 -200
- package/dist/chunk-OO3DRYK7.mjs.map +1 -0
- package/dist/{chunk-GWCEMDVR.mjs → chunk-PLAXOOX5.mjs} +232 -7
- package/dist/chunk-PLAXOOX5.mjs.map +1 -0
- package/dist/{chunk-JRIPCMYC.mjs → chunk-VOZWDM3L.mjs} +283 -193
- package/dist/chunk-VOZWDM3L.mjs.map +1 -0
- package/dist/{chunk-JCIRYQ4V.mjs → chunk-ZDQWGQW7.mjs} +10 -4
- package/dist/chunk-ZDQWGQW7.mjs.map +1 -0
- package/dist/components/atmosphere.d.ts +2 -0
- package/dist/components/atmosphere.d.ts.map +1 -1
- package/dist/components/camera.d.ts +20 -4
- package/dist/components/camera.d.ts.map +1 -1
- package/dist/components/mesh-filter.d.ts +6 -5
- package/dist/components/mesh-filter.d.ts.map +1 -1
- package/dist/components/motion-blur.d.ts +1 -0
- package/dist/components/motion-blur.d.ts.map +1 -1
- package/dist/construct-renderer.mjs +2865 -526
- package/dist/construct-renderer.mjs.map +1 -1
- package/dist/device/gpu-residency.d.ts +6 -0
- package/dist/device/gpu-residency.d.ts.map +1 -1
- package/dist/environment/analytic-fog.d.ts +6 -0
- package/dist/environment/analytic-fog.d.ts.map +1 -0
- package/dist/errors/render.d.ts +6 -2
- 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/environment.d.ts +2 -0
- package/dist/extract/environment.d.ts.map +1 -1
- package/dist/features/error-reporting.d.ts +13 -0
- package/dist/features/error-reporting.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/motion-blur/motion-blur-feature.d.ts +20 -2
- package/dist/features/motion-blur/motion-blur-feature.d.ts.map +1 -1
- package/dist/features/motion-blur/motion-blur-params.d.ts +21 -0
- package/dist/features/motion-blur/motion-blur-params.d.ts.map +1 -1
- package/dist/features/motion-blur/motion-blur-runtime.d.ts +54 -0
- package/dist/features/motion-blur/motion-blur-runtime.d.ts.map +1 -0
- package/dist/features/plan.d.ts +7 -4
- package/dist/features/plan.d.ts.map +1 -1
- package/dist/features/prepared-gpu-work.d.ts +9 -5
- package/dist/features/prepared-gpu-work.d.ts.map +1 -1
- package/dist/features/render-graph-compute.d.ts.map +1 -1
- package/dist/features/render-graph-contribution.d.ts.map +1 -1
- package/dist/gpu-driven/material-artifacts.d.ts.map +1 -1
- package/dist/gpu-driven/prepared-draw.d.ts +7 -0
- package/dist/gpu-driven/prepared-draw.d.ts.map +1 -1
- package/dist/gpu-driven/production-raster.d.ts +3 -1
- package/dist/gpu-driven/production-raster.d.ts.map +1 -1
- package/dist/gpu-driven/view-gpu.d.ts +9 -0
- package/dist/gpu-driven/view-gpu.d.ts.map +1 -1
- package/dist/gpu-scene.d.ts +6 -1
- package/dist/gpu-scene.d.ts.map +1 -1
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +5 -5
- package/dist/inspection-types.d.ts +43 -2
- package/dist/inspection-types.d.ts.map +1 -1
- package/dist/instances.d.ts +8 -1
- package/dist/instances.d.ts.map +1 -1
- package/dist/internal.mjs +6 -6
- package/dist/pipeline/standard-post.d.ts +28 -19
- package/dist/pipeline/standard-post.d.ts.map +1 -1
- package/dist/pipeline-spec.d.ts +2 -2
- package/dist/record/frame-snapshot.d.ts +3 -0
- 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 +5 -2
- package/dist/record/frame.d.ts.map +1 -1
- package/dist/record/main-pass-geometry.d.ts.map +1 -1
- package/dist/record/mesh-ssbo.d.ts +6 -5
- package/dist/record/mesh-ssbo.d.ts.map +1 -1
- package/dist/record/render-context.d.ts +12 -28
- package/dist/record/render-context.d.ts.map +1 -1
- package/dist/record/shadow-pass.d.ts.map +1 -1
- package/dist/record/skybox-post-pass.d.ts +5 -3
- package/dist/record/skybox-post-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.map +1 -1
- package/dist/render-contract.d.ts +24 -4
- package/dist/render-contract.d.ts.map +1 -1
- package/dist/render-pipeline.d.ts +3 -1
- package/dist/render-pipeline.d.ts.map +1 -1
- package/dist/render-system-extract-tail.d.ts.map +1 -1
- package/dist/render-system-extract.d.ts +8 -1
- package/dist/render-system-extract.d.ts.map +1 -1
- package/dist/render-system.d.ts +7 -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/temporal/frame-coordinator.d.ts.map +1 -1
- package/dist/temporal/frame.d.ts +7 -0
- package/dist/temporal/frame.d.ts.map +1 -1
- package/dist/temporal/index.mjs +5 -5
- package/dist/temporal/view.d.ts +6 -1
- package/dist/temporal/view.d.ts.map +1 -1
- package/dist/typed-render-graph-primitives.d.ts +10 -7
- package/dist/typed-render-graph-primitives.d.ts.map +1 -1
- package/dist/volume/component.d.ts +0 -1
- package/dist/volume/component.d.ts.map +1 -1
- package/dist/volume/passes.d.ts.map +1 -1
- package/dist/volume/temporal.d.ts +3 -1
- package/dist/volume/temporal.d.ts.map +1 -1
- package/package.json +21 -21
- package/src/__tests__/analytic-fog-graph.unit.test.ts +199 -0
- package/src/__tests__/analytic-fog-optics.unit.test.ts +38 -0
- package/src/__tests__/bloom-exact-zero.unit.test.ts +112 -18
- package/src/__tests__/bloom-lifecycle.integration.test.ts +17 -4
- package/src/__tests__/dynamic-resolution-plugin.integration.test.ts +20 -0
- package/src/__tests__/environment-fog-lanes.integration.test.ts +14 -0
- package/src/__tests__/environment-selection.unit.test.ts +12 -0
- package/src/__tests__/factory-contract.integration.test.ts +331 -68
- package/src/__tests__/frame-camera-selection.unit.test.ts +39 -1
- package/src/__tests__/frame-plan-contract.unit.test.ts +2 -0
- package/src/__tests__/gpu-driven-indirect-raster-evidence.ts +2 -1
- package/src/__tests__/gpu-driven-shadow-views.dawn.test.ts +1 -1
- package/src/__tests__/gpu-driven-shadow-views.integration.test.ts +1 -1
- package/src/__tests__/gpu-driven-view-gpu-evidence.ts +11 -0
- package/src/__tests__/gpu-resource-store-stride.unit.test.ts +12 -0
- package/src/__tests__/gpu-scene.unit.test.ts +91 -0
- package/src/__tests__/instances-store.unit.test.ts +75 -0
- package/src/__tests__/mesh-submission-lifetime.unit.test.ts +31 -0
- package/src/__tests__/motion-blur-compute.dawn.test.ts +583 -0
- package/src/__tests__/prepared-gpu-driven-pbr.integration.test.ts +21 -0
- package/src/__tests__/prepared-graphics-lifecycle.unit.test.ts +86 -0
- package/src/__tests__/public-surface.test-d.ts +8 -0
- package/src/__tests__/render-error-code-owner.test-d.ts +2 -0
- package/src/__tests__/render-feature-error-reporting.unit.test.ts +24 -0
- package/src/__tests__/render-feature-stage-fault-recovery.unit.test.ts +23 -0
- package/src/__tests__/render-scene-temporal-retry.unit.test.ts +31 -0
- package/src/__tests__/renderer-frame-transaction.integration.test.ts +7 -1
- package/src/__tests__/shader-manifest-fixture.ts +4 -4
- package/src/__tests__/skinned-shadow-caster.test.ts +2 -0
- package/src/__tests__/standard-lighting-write.unit.test.ts +2 -1
- package/src/__tests__/standard-pipeline.dawn.test.ts +1 -1
- package/src/__tests__/standard-pipeline.integration.test.ts +18 -8
- package/src/__tests__/temporal-reset-matrix.unit.test.ts +10 -0
- package/src/__tests__/temporal-view.unit.test.ts +2 -1
- package/src/__tests__/typed-pipeline-topology.unit.test.ts +20 -4
- package/src/__tests__/volume-optics-oracle.unit.test.ts +3 -1
- package/src/__tests__/volumetric-fog-budget-recovery.integration.test.ts +177 -13
- package/src/__tests__/volumetric-fog-stage-readback.dawn.test.ts +447 -61
- package/src/__tests__/volumetric-fog-temporal.unit.test.ts +27 -0
- package/src/__tests__/volumetric-fog-topology.unit.test.ts +19 -3
- package/src/assembly/analytic-fog-registration.ts +14 -0
- package/src/assembly/fxaa-registration.ts +17 -0
- package/src/assembly/lod-observation.ts +12 -0
- package/src/assembly/motion-blur-registration.ts +17 -0
- package/src/assembly/renderer-facade.ts +2 -0
- package/src/assembly/temporal-post-process-prewarm.ts +40 -0
- package/src/assembly/webgpu-ready-contract.ts +8 -3
- package/src/assembly/webgpu-ready.ts +181 -245
- package/src/assembly/webgpu-renderer.ts +16 -31
- package/src/bloom-admission.ts +21 -0
- package/src/components/__tests__/motion-blur.unit.test.ts +1 -0
- package/src/components/atmosphere.ts +4 -0
- package/src/components/camera.ts +66 -10
- package/src/components/mesh-filter.ts +11 -9
- package/src/components/motion-blur.ts +1 -0
- package/src/device/gpu-residency.ts +56 -12
- package/src/environment/analytic-fog.ts +44 -0
- package/src/environment/background.ts +2 -2
- package/src/errors/render.ts +14 -1
- package/src/extract/camera.ts +20 -7
- package/src/extract/contracts.ts +7 -0
- package/src/extract/environment.ts +4 -0
- package/src/features/error-reporting.ts +78 -0
- package/src/features/host.ts +25 -12
- package/src/features/motion-blur/__tests__/motion-blur-feature.unit.test.ts +111 -1
- package/src/features/motion-blur/__tests__/motion-blur-params.unit.test.ts +58 -3
- package/src/features/motion-blur/motion-blur-feature.ts +1519 -15
- package/src/features/motion-blur/motion-blur-params.ts +70 -2
- package/src/features/motion-blur/motion-blur-runtime.ts +176 -0
- package/src/features/plan.ts +25 -8
- package/src/features/prepared-gpu-work.ts +86 -35
- package/src/features/render-graph-compute.ts +13 -5
- package/src/features/render-graph-contribution.ts +2 -0
- package/src/gpu-driven/material-artifacts.ts +2 -7
- package/src/gpu-driven/prepared-draw.ts +15 -10
- package/src/gpu-driven/production-raster.ts +83 -7
- package/src/gpu-driven/view-gpu.ts +17 -0
- package/src/gpu-scene.ts +188 -21
- package/src/index.ts +32 -0
- package/src/inspection-types.ts +60 -2
- package/src/instances.ts +80 -1
- package/src/pipeline/standard-post.ts +307 -78
- package/src/pipeline-spec.ts +5 -5
- package/src/points-lines/__tests__/view-ubo.unit.test.ts +2 -1
- package/src/record/__tests__/temporal-payload.unit.test.ts +2 -1
- package/src/record/frame-snapshot.ts +5 -1
- package/src/record/frame-targets.ts +10 -6
- package/src/record/frame.ts +163 -22
- package/src/record/main-pass-geometry.ts +30 -1
- package/src/record/main-pass-sprite-draws.ts +6 -1
- package/src/record/mesh-ssbo.ts +43 -6
- package/src/record/render-context.ts +12 -28
- package/src/record/shadow-pass.ts +6 -1
- package/src/record/skybox-post-pass.ts +122 -196
- package/src/record/typed-frame-graph.ts +153 -9
- package/src/recovery/render-system-candidate.ts +22 -10
- package/src/render-contract.ts +23 -4
- package/src/render-pipeline.ts +6 -1
- package/src/render-system-extract-tail.ts +16 -0
- package/src/render-system-extract.ts +45 -13
- package/src/render-system.ts +255 -120
- package/src/scene/render-scene.ts +85 -4
- package/src/temporal/__tests__/temporal-frame-transaction.unit.test.ts +36 -0
- package/src/temporal/frame-coordinator.ts +8 -1
- package/src/temporal/frame.ts +20 -0
- package/src/temporal/view.ts +13 -2
- package/src/typed-render-graph-primitives.ts +121 -48
- package/src/volume/component.ts +0 -1
- package/src/volume/passes.ts +8 -4
- package/src/volume/resources.ts +1 -1
- package/src/volume/temporal.ts +11 -0
- package/dist/chunk-4NNZQCL3.mjs.map +0 -1
- package/dist/chunk-6TFBXLRJ.mjs.map +0 -1
- package/dist/chunk-DRR7D3KX.mjs.map +0 -1
- package/dist/chunk-GWCEMDVR.mjs.map +0 -1
- package/dist/chunk-JCIRYQ4V.mjs.map +0 -1
- package/dist/chunk-JRIPCMYC.mjs.map +0 -1
package/src/render-system.ts
CHANGED
|
@@ -39,6 +39,7 @@ import {
|
|
|
39
39
|
projectDirectionalShadowInspectionSource,
|
|
40
40
|
} from './assembly/directional-shadow-inspection';
|
|
41
41
|
import { createGpuDrivenOwner } from './assembly/gpu-driven-owner';
|
|
42
|
+
import { standardBloomAdmitted } from './bloom-admission';
|
|
42
43
|
import { createClusterBinScratch } from './cluster-binner';
|
|
43
44
|
import { EnvironmentLifecycle } from './environment/lifecycle';
|
|
44
45
|
import {
|
|
@@ -48,11 +49,24 @@ import {
|
|
|
48
49
|
} from './errors/render';
|
|
49
50
|
import { projectDepthOfFieldInspection } from './features/depth-of-field/depth-of-field-inspection';
|
|
50
51
|
import { resolveDepthOfFieldFrameParams } from './features/depth-of-field/depth-of-field-params';
|
|
52
|
+
import { reportPendingRenderFeatureErrors } from './features/error-reporting';
|
|
51
53
|
import {
|
|
52
54
|
type RenderFeaturePreparedGraphicsResolverInput,
|
|
53
55
|
runRenderFeatureFrame,
|
|
54
56
|
settlePreparedGraphicsCompletion,
|
|
55
57
|
} from './features/host';
|
|
58
|
+
import {
|
|
59
|
+
createMotionBlurFeature,
|
|
60
|
+
type MotionBlurFeatureInput,
|
|
61
|
+
} from './features/motion-blur/motion-blur-feature';
|
|
62
|
+
import {
|
|
63
|
+
MotionBlurValidationError,
|
|
64
|
+
motionBlurTemporalDemand,
|
|
65
|
+
} from './features/motion-blur/motion-blur-params';
|
|
66
|
+
import {
|
|
67
|
+
planMotionBlurFrame,
|
|
68
|
+
projectMotionBlurInspection,
|
|
69
|
+
} from './features/motion-blur/motion-blur-runtime';
|
|
56
70
|
import { createFeatureNoiseResolver } from './features/noise-texture';
|
|
57
71
|
import {
|
|
58
72
|
createRenderFeatureGpuWorkOwner,
|
|
@@ -83,6 +97,7 @@ import type {
|
|
|
83
97
|
TemporalTargetInspection,
|
|
84
98
|
TransmissionInspection,
|
|
85
99
|
} from './inspection-types';
|
|
100
|
+
import { emptyBloomInspection } from './inspection-types';
|
|
86
101
|
import { buildOcclusionProxyVertices } from './occlusion-proxy';
|
|
87
102
|
import {
|
|
88
103
|
AUTO_EXPOSURE_HISTOGRAM_BYTES,
|
|
@@ -542,7 +557,10 @@ export interface RenderSystem {
|
|
|
542
557
|
options: FrameObservationOptions,
|
|
543
558
|
): Promise<Result<FrameObservation, ObservationUnavailableError>>;
|
|
544
559
|
/** Resolve the renderer-owned GPU LOD counters for the last accepted submit. */
|
|
545
|
-
observeLodOcclusion(
|
|
560
|
+
observeLodOcclusion(receipt?: {
|
|
561
|
+
readonly frameId: number;
|
|
562
|
+
readonly deviceGeneration: number;
|
|
563
|
+
}): Promise<void>;
|
|
546
564
|
/** Internal same-frame graph target access for backend diagnostics. */
|
|
547
565
|
getCurrentGraphTarget(name: string): CurrentGraphTarget | undefined;
|
|
548
566
|
/** Internal test capture copied into the draw's command submission. */
|
|
@@ -580,6 +598,8 @@ export interface RenderSystem {
|
|
|
580
598
|
readonly temporal: TemporalInspection;
|
|
581
599
|
readonly bloom: BloomInspection;
|
|
582
600
|
readonly motionBlurInspection: MotionBlurInspection | undefined;
|
|
601
|
+
/** The last extraction validation failure, preserved for public draw(). */
|
|
602
|
+
readonly motionBlurInvalidParams: MotionBlurValidationError | undefined;
|
|
583
603
|
readonly depthOfFieldInspection: DepthOfFieldInspection | undefined;
|
|
584
604
|
readonly temporalTargetInspection: TemporalTargetInspection | undefined;
|
|
585
605
|
readonly lodOcclusionInspection: LodOcclusionInspection | undefined;
|
|
@@ -723,13 +743,6 @@ function reportPreparedGraphicsCompletionError(
|
|
|
723
743
|
);
|
|
724
744
|
}
|
|
725
745
|
|
|
726
|
-
function isPendingRenderFeaturePreparation(error: RenderError): boolean {
|
|
727
|
-
return (
|
|
728
|
-
error.code === 'render-feature-preparation-failed' &&
|
|
729
|
-
error.detail.reason.startsWith('rhi-not-available:')
|
|
730
|
-
);
|
|
731
|
-
}
|
|
732
|
-
|
|
733
746
|
function makePreparedPipelinePendingError(): RhiError {
|
|
734
747
|
return new RhiError({
|
|
735
748
|
code: 'rhi-not-available',
|
|
@@ -897,6 +910,24 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
897
910
|
let preparedFeatureSkylightResources: SkylightBindGroupResources | undefined;
|
|
898
911
|
const dynamicGeometryFrames = createDynamicGeometryFrameBindings();
|
|
899
912
|
let latestCamera: CameraSnapshot | undefined;
|
|
913
|
+
// Last public parameter failure; cleared only after a valid extraction.
|
|
914
|
+
let lastMotionBlurInvalidParams: MotionBlurValidationError | undefined;
|
|
915
|
+
// Lazily install the compute lane when a capable frame demands it.
|
|
916
|
+
let motionBlurFeatureInput: MotionBlurFeatureInput | undefined;
|
|
917
|
+
const motionBlurFeature = createMotionBlurFeature(() => motionBlurFeatureInput);
|
|
918
|
+
const ensureMotionBlurFeature = (): void => {
|
|
919
|
+
const host = internals.featureHost;
|
|
920
|
+
if (
|
|
921
|
+
host === undefined ||
|
|
922
|
+
host.features.some((feature) => feature.identity === 'forgeax.motion-blur')
|
|
923
|
+
) {
|
|
924
|
+
return;
|
|
925
|
+
}
|
|
926
|
+
const installed = host.install(
|
|
927
|
+
motionBlurFeature as import('./features/types').RenderFeature<unknown>,
|
|
928
|
+
);
|
|
929
|
+
if (!installed.ok) internals.errorRegistry.fire(installed.error);
|
|
930
|
+
};
|
|
900
931
|
const pointsLinesOwner = new StandardPointsLinesOwner(internals);
|
|
901
932
|
const instanceCollections = new InstanceCollectionStore();
|
|
902
933
|
const reflectionProbeOwner = new ReflectionProbeRecordOwner(internals);
|
|
@@ -1291,6 +1322,11 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
1291
1322
|
// tiles until the first frame with a castShadow spot (AC-03).
|
|
1292
1323
|
spotShadowSnapshots: [],
|
|
1293
1324
|
};
|
|
1325
|
+
// A feature that is explicitly recoverable on the next frame must not
|
|
1326
|
+
// publish the same transient failure on every render tick. Keep one
|
|
1327
|
+
// renderer-owned cooldown per structured feature failure while retaining
|
|
1328
|
+
// the original error for the first and periodic reports.
|
|
1329
|
+
const pendingFeatureErrorLastReportedFrame = new Map<string, number>();
|
|
1294
1330
|
const resolveSsrDependencies = (requested: boolean): SsrDependenciesInspection => {
|
|
1295
1331
|
// Explicit SSR capability preparation belongs to initialization. Inspection
|
|
1296
1332
|
// only projects receipts and never starts work or creates image history.
|
|
@@ -1752,6 +1788,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
1752
1788
|
readonly visible: number;
|
|
1753
1789
|
readonly occluded: number;
|
|
1754
1790
|
readonly lodHistogram: readonly { readonly level: number; readonly count: number }[];
|
|
1791
|
+
readonly submit?: { readonly frameId: number; readonly deviceGeneration: number };
|
|
1755
1792
|
readonly worldSelections?: readonly {
|
|
1756
1793
|
readonly worldKey: number;
|
|
1757
1794
|
readonly primitiveSlot: number;
|
|
@@ -1763,9 +1800,11 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
1763
1800
|
}[];
|
|
1764
1801
|
}
|
|
1765
1802
|
| undefined,
|
|
1803
|
+
targetInspection: LodOcclusionInspection | undefined = lastLodOcclusionInspection,
|
|
1804
|
+
targetWorldAttachments: ReadonlyMap<number, string> = lastLodWorldAttachments,
|
|
1766
1805
|
): void => {
|
|
1767
|
-
if (selection === undefined ||
|
|
1768
|
-
const inspection =
|
|
1806
|
+
if (selection === undefined || targetInspection === undefined) return;
|
|
1807
|
+
const inspection = targetInspection;
|
|
1769
1808
|
// The GPU readback histogram is the selector fact, while final submitted
|
|
1770
1809
|
// counts are owned by the persistent visibility projection. Keeping the
|
|
1771
1810
|
// projection count here excludes ordinary non-LOD geometry (for example a
|
|
@@ -1777,7 +1816,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
1777
1816
|
const selectionsByAttachment = new Map<string, (typeof worldSelections)[number][]>();
|
|
1778
1817
|
let attributionValid = true;
|
|
1779
1818
|
for (const selected of worldSelections) {
|
|
1780
|
-
const attachmentId =
|
|
1819
|
+
const attachmentId = targetWorldAttachments.get(selected.worldKey);
|
|
1781
1820
|
if (attachmentId === undefined) {
|
|
1782
1821
|
attributionValid = false;
|
|
1783
1822
|
break;
|
|
@@ -1790,15 +1829,16 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
1790
1829
|
const nextWorlds = worlds.map((world) => {
|
|
1791
1830
|
const selected = selectionsByAttachment.get(world.attachmentId);
|
|
1792
1831
|
const baseRow = world.rows[0];
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1832
|
+
// A World with only plain meshes has no LOD selection row. Keep its
|
|
1833
|
+
// projection-only receipt and allow Worlds with valid LOD rows to
|
|
1834
|
+
// retain same-submit attribution. Unknown selected world keys still
|
|
1835
|
+
// fail closed above.
|
|
1836
|
+
if (selected === undefined || baseRow === undefined) return world;
|
|
1837
|
+
// The projection row is intentionally CPU-scoped and may omit
|
|
1838
|
+
// selector-only candidates that remain in the full GPU plan. The
|
|
1839
|
+
// same-submit GPU row owns the denominator; comparing it to the
|
|
1840
|
+
// projection count would reject a valid receipt (for example 11 GPU
|
|
1841
|
+
// candidates versus 10 CPU-admitted renderables).
|
|
1802
1842
|
return Object.freeze({
|
|
1803
1843
|
...world,
|
|
1804
1844
|
attribution: Object.freeze({
|
|
@@ -1828,7 +1868,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
1828
1868
|
lastLodOcclusionInspection = inspectLodOcclusion({
|
|
1829
1869
|
...inspection,
|
|
1830
1870
|
count: {
|
|
1831
|
-
...
|
|
1871
|
+
...inspection.count,
|
|
1832
1872
|
candidates: selection.candidateCount,
|
|
1833
1873
|
visible: selection.visible,
|
|
1834
1874
|
occluded: selection.occluded,
|
|
@@ -2274,24 +2314,20 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2274
2314
|
});
|
|
2275
2315
|
},
|
|
2276
2316
|
get motionBlurInspection(): MotionBlurInspection | undefined {
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
frameState.
|
|
2283
|
-
frameState.
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
passName: 'motion-blur',
|
|
2292
|
-
historyWrites: 0,
|
|
2293
|
-
...(unavailable ? { lastFailure: 'scene-data-unavailable' as const } : {}),
|
|
2294
|
-
};
|
|
2317
|
+
return projectMotionBlurInspection({
|
|
2318
|
+
camera: latestCamera,
|
|
2319
|
+
invalidParams: lastMotionBlurInvalidParams,
|
|
2320
|
+
capabilities: internals.device.caps,
|
|
2321
|
+
acceptedTemporal: frameState.lastSuccessfulTemporalView,
|
|
2322
|
+
transaction: frameState.temporalFrameTransaction.inspect(),
|
|
2323
|
+
execution: frameState.motionBlurExecution,
|
|
2324
|
+
temporalFrameId: frameState.temporalFrame?.frameId,
|
|
2325
|
+
deviceGeneration: internals.deviceScope.generation,
|
|
2326
|
+
graphGeneration: frameState.graphGeneration,
|
|
2327
|
+
});
|
|
2328
|
+
},
|
|
2329
|
+
get motionBlurInvalidParams(): MotionBlurValidationError | undefined {
|
|
2330
|
+
return lastMotionBlurInvalidParams;
|
|
2295
2331
|
},
|
|
2296
2332
|
get depthOfFieldInspection(): DepthOfFieldInspection | undefined {
|
|
2297
2333
|
const camera = latestCamera;
|
|
@@ -2354,22 +2390,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2354
2390
|
const lifecycle = resources?.inspectBloomResources?.(
|
|
2355
2391
|
frameState.compiledFrameGraph?.inspect(),
|
|
2356
2392
|
);
|
|
2357
|
-
return Object.freeze(
|
|
2358
|
-
lifecycle ?? {
|
|
2359
|
-
graphStatus: 'empty',
|
|
2360
|
-
enabled: false,
|
|
2361
|
-
targetCount: 0,
|
|
2362
|
-
targetBytes: 0,
|
|
2363
|
-
resourceCount: 0,
|
|
2364
|
-
passCount: 0,
|
|
2365
|
-
encodeCount: 0,
|
|
2366
|
-
bindGroupCount: 0,
|
|
2367
|
-
uploadCount: 0,
|
|
2368
|
-
residentChildBytes: 0,
|
|
2369
|
-
generation: 0,
|
|
2370
|
-
state: 'off',
|
|
2371
|
-
},
|
|
2372
|
-
);
|
|
2393
|
+
return Object.freeze(lifecycle ?? emptyBloomInspection());
|
|
2373
2394
|
},
|
|
2374
2395
|
get transmission(): TransmissionInspection | undefined {
|
|
2375
2396
|
return lastTransmissionInspection;
|
|
@@ -2444,6 +2465,10 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2444
2465
|
const profileSession = internals.profiler?.activeSession();
|
|
2445
2466
|
let ownsProfileFrame = false;
|
|
2446
2467
|
let submitted = false;
|
|
2468
|
+
// A prior failed record/submit may have staged a temporal capture. A
|
|
2469
|
+
// capture belongs only to the draw call that created it; discard it
|
|
2470
|
+
// before this call can prepare or commit a new candidate.
|
|
2471
|
+
persistentRenderScene.discardTemporalFrame();
|
|
2447
2472
|
// A failed draw must never leave a previous frame eligible to publish a
|
|
2448
2473
|
// newly accepted dynamic-geometry candidate.
|
|
2449
2474
|
dynamicGeometryFrames.begin();
|
|
@@ -2475,55 +2500,67 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2475
2500
|
dispatchCounts.unlit = 0;
|
|
2476
2501
|
|
|
2477
2502
|
const resourceWorld = compositionWorlds[resourceOwner] as World;
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
:
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2503
|
+
let frame: ReturnType<PersistentRenderScene['extractComposition']>;
|
|
2504
|
+
try {
|
|
2505
|
+
frame = runProfiledRenderPhase(profileSession, 'extract', () => {
|
|
2506
|
+
return persistentRenderScene.extractComposition(
|
|
2507
|
+
compositionWorlds,
|
|
2508
|
+
{ cameraOwner, resourceOwner },
|
|
2509
|
+
internals.assets.catalogEpoch,
|
|
2510
|
+
(renderables) =>
|
|
2511
|
+
extractFrames(
|
|
2512
|
+
compositionWorlds,
|
|
2513
|
+
{
|
|
2514
|
+
cameraOwner,
|
|
2515
|
+
resourceOwner,
|
|
2516
|
+
...(cameraEntityKey === undefined ? {} : { cameraEntityKey }),
|
|
2517
|
+
},
|
|
2518
|
+
internals.assets,
|
|
2519
|
+
internals.getPipelineState(),
|
|
2520
|
+
persistentRenderScene.materialSnapshotCacheStore(),
|
|
2521
|
+
{
|
|
2522
|
+
...(internals.device.caps.backendKind === 'null'
|
|
2523
|
+
? {}
|
|
2524
|
+
: {
|
|
2525
|
+
materialContext: {
|
|
2526
|
+
backend:
|
|
2527
|
+
internals.device.caps.backendKind === 'wgpu-webgl2'
|
|
2528
|
+
? ('webgl2' as const)
|
|
2529
|
+
: internals.device.caps.backendKind,
|
|
2530
|
+
capability: internals.device.caps.storageBuffer
|
|
2531
|
+
? ('storage-buffer' as const)
|
|
2532
|
+
: ('uniform-fallback' as const),
|
|
2533
|
+
pipeline: 'forward' as const,
|
|
2534
|
+
geometry: 'mesh' as const,
|
|
2535
|
+
pass: 'forward' as const,
|
|
2536
|
+
profile: 'forgeax-material-wgsl-v1' as const,
|
|
2537
|
+
toolchain: 'naga-oil' as const,
|
|
2538
|
+
instrumentation: 'none' as const,
|
|
2539
|
+
},
|
|
2540
|
+
}),
|
|
2541
|
+
cull: 'none',
|
|
2542
|
+
retainHidden: true,
|
|
2543
|
+
renderables,
|
|
2544
|
+
instanceCollections,
|
|
2545
|
+
...(!internals.device.caps.storageBuffer ||
|
|
2546
|
+
internals.getMaterialShaderArtifact === undefined
|
|
2547
|
+
? {}
|
|
2548
|
+
: { getMaterialShaderArtifact: internals.getMaterialShaderArtifact }),
|
|
2549
|
+
},
|
|
2550
|
+
),
|
|
2551
|
+
compositionLeases,
|
|
2552
|
+
);
|
|
2553
|
+
});
|
|
2554
|
+
} catch (cause) {
|
|
2555
|
+
if (cause instanceof MotionBlurValidationError) {
|
|
2556
|
+
lastMotionBlurInvalidParams = cause;
|
|
2557
|
+
latestCamera = undefined;
|
|
2558
|
+
internals.errorRegistry.fire(cause);
|
|
2559
|
+
return false;
|
|
2560
|
+
}
|
|
2561
|
+
throw cause;
|
|
2562
|
+
}
|
|
2563
|
+
lastMotionBlurInvalidParams = undefined;
|
|
2527
2564
|
const {
|
|
2528
2565
|
cameras: extractedCameras,
|
|
2529
2566
|
cubeCameras,
|
|
@@ -2760,6 +2797,15 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2760
2797
|
const submissionRenderables = visibilityProjection.renderables;
|
|
2761
2798
|
const submissionDispatch = visibilityProjection.dispatch;
|
|
2762
2799
|
const inspectionCamera = latestCamera;
|
|
2800
|
+
// The public frame receipt is allocated by WebGPURenderer immediately
|
|
2801
|
+
// before this draw (`observationFrameId`). RenderSystem's private
|
|
2802
|
+
// frameNumber is an internal generation and also advances on failed
|
|
2803
|
+
// record attempts, so it cannot be used as receipt identity. Keep the
|
|
2804
|
+
// internal generation for recovery/visibility state, but bind the LOD
|
|
2805
|
+
// inspection to the frame id that the caller will receive.
|
|
2806
|
+
const lodSubmitFrameId =
|
|
2807
|
+
(internals as RenderSystemInternals & { readonly observationFrameId?: number })
|
|
2808
|
+
.observationFrameId ?? frameState.frameNumber;
|
|
2763
2809
|
let lodCandidateCountForFrame = 0;
|
|
2764
2810
|
if (inspectionCamera !== undefined) {
|
|
2765
2811
|
const firstRenderable = renderables[0];
|
|
@@ -2802,7 +2848,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2802
2848
|
renderables,
|
|
2803
2849
|
submissionRenderables,
|
|
2804
2850
|
inspectionCamera,
|
|
2805
|
-
|
|
2851
|
+
lodSubmitFrameId,
|
|
2806
2852
|
worldKeys,
|
|
2807
2853
|
slotByEntity,
|
|
2808
2854
|
{
|
|
@@ -2834,7 +2880,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2834
2880
|
firstRenderable === undefined
|
|
2835
2881
|
? 'none'
|
|
2836
2882
|
: `asset-handle:${firstRenderable.assetHandle}`,
|
|
2837
|
-
sourceKey: `render-frame:${
|
|
2883
|
+
sourceKey: `render-frame:${lodSubmitFrameId}`,
|
|
2838
2884
|
},
|
|
2839
2885
|
view: {
|
|
2840
2886
|
attachmentId:
|
|
@@ -2847,7 +2893,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2847
2893
|
primitiveSlot: 0,
|
|
2848
2894
|
slotGeneration: persistentRenderScene.inspect().topology.revision,
|
|
2849
2895
|
},
|
|
2850
|
-
generation:
|
|
2896
|
+
generation: lodSubmitFrameId,
|
|
2851
2897
|
count: {
|
|
2852
2898
|
candidates: candidateCount,
|
|
2853
2899
|
visible: inspectionRenderables.length,
|
|
@@ -2866,7 +2912,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2866
2912
|
visible: true,
|
|
2867
2913
|
})),
|
|
2868
2914
|
submit: {
|
|
2869
|
-
frameId:
|
|
2915
|
+
frameId: lodSubmitFrameId,
|
|
2870
2916
|
build: resolveInspectionBuild(internals),
|
|
2871
2917
|
deviceGeneration: internals.deviceScope.generation,
|
|
2872
2918
|
},
|
|
@@ -2878,7 +2924,14 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2878
2924
|
lastLodWorldAttachments = new Map();
|
|
2879
2925
|
}
|
|
2880
2926
|
const temporalDemanded =
|
|
2881
|
-
cameras[0]?.antialias === 'taa' ||
|
|
2927
|
+
cameras[0]?.antialias === 'taa' ||
|
|
2928
|
+
(cameras[0]?.motionBlur !== undefined &&
|
|
2929
|
+
motionBlurTemporalDemand({
|
|
2930
|
+
shutterAngle: cameras[0].motionBlur.shutterAngle,
|
|
2931
|
+
maxRadiusPixels: cameras[0].motionBlur.maxRadiusPixels,
|
|
2932
|
+
sampleCount: cameras[0].motionBlur.sampleCount,
|
|
2933
|
+
targetFps: cameras[0].motionBlur.targetFps ?? 60,
|
|
2934
|
+
}));
|
|
2882
2935
|
if (temporalDemanded) {
|
|
2883
2936
|
persistentRenderScene.prepareTemporalFrame(submissionRenderables);
|
|
2884
2937
|
}
|
|
@@ -2989,6 +3042,44 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
2989
3042
|
storageBuffer: internals.device.caps.storageBuffer,
|
|
2990
3043
|
multisample: internals.device.caps.backendKind !== 'wgpu-webgl2',
|
|
2991
3044
|
});
|
|
3045
|
+
const motionBlurParams = cameras[0]?.motionBlur;
|
|
3046
|
+
let motionBlurDelta = 0;
|
|
3047
|
+
try {
|
|
3048
|
+
const delta = (compositionWorlds[cameraOwner] as World).getResource(Time).delta;
|
|
3049
|
+
motionBlurDelta = Number.isFinite(delta) ? Math.max(0, delta) : 0;
|
|
3050
|
+
} catch {
|
|
3051
|
+
motionBlurDelta = 0;
|
|
3052
|
+
}
|
|
3053
|
+
const acceptedSampleTime = frameState.lastSuccessfulTemporalView?.sampleTimeSeconds;
|
|
3054
|
+
const cameraViewIdentity = `camera:${cameras[0]?.entityKey ?? 0}`;
|
|
3055
|
+
const canvasWidth = Math.max(1, internals.canvas.width);
|
|
3056
|
+
const canvasHeight = Math.max(1, internals.canvas.height);
|
|
3057
|
+
const motionBlurPlan = planMotionBlurFrame({
|
|
3058
|
+
params: motionBlurParams,
|
|
3059
|
+
sampleTimeSeconds: opts.sampleTimeSeconds,
|
|
3060
|
+
acceptedSampleTimeSeconds: acceptedSampleTime,
|
|
3061
|
+
fallbackDeltaSeconds: motionBlurDelta,
|
|
3062
|
+
acceptedTemporal: frameState.lastSuccessfulTemporalView,
|
|
3063
|
+
temporalReset: opts.temporalReset === true,
|
|
3064
|
+
width: canvasWidth,
|
|
3065
|
+
height: canvasHeight,
|
|
3066
|
+
cameraViewIdentity,
|
|
3067
|
+
historyVersion: cameras[0]?.historyVersion ?? 0,
|
|
3068
|
+
environmentSignature: environment?.environmentSignature ?? '',
|
|
3069
|
+
fogSignature: environment?.fogSignature ?? '',
|
|
3070
|
+
deviceGeneration: internals.deviceScope?.generation ?? 0,
|
|
3071
|
+
});
|
|
3072
|
+
const demandedMotionBlur = motionBlurPlan.demanded;
|
|
3073
|
+
motionBlurFeatureInput = motionBlurPlan.featureInput;
|
|
3074
|
+
if (
|
|
3075
|
+
demandedMotionBlur &&
|
|
3076
|
+
internals.device.caps.compute === true &&
|
|
3077
|
+
internals.device.caps.storageBuffer === true &&
|
|
3078
|
+
internals.device.caps.storageTexture === true &&
|
|
3079
|
+
internals.device.caps.rgba16floatRenderable === true
|
|
3080
|
+
) {
|
|
3081
|
+
ensureMotionBlurFeature();
|
|
3082
|
+
}
|
|
2992
3083
|
preparedFeatureSkylightResources =
|
|
2993
3084
|
preparedPipelineState === null
|
|
2994
3085
|
? undefined
|
|
@@ -3001,6 +3092,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3001
3092
|
worlds: compositionWorlds,
|
|
3002
3093
|
owner: resourceOwner,
|
|
3003
3094
|
frameNumber: frameState.frameNumber,
|
|
3095
|
+
frameSize: { width: internals.canvas.width, height: internals.canvas.height },
|
|
3004
3096
|
visibilitySnapshots: frame.featureVisibilitySnapshots,
|
|
3005
3097
|
hiddenEntityReports: frame.hiddenEntityReports,
|
|
3006
3098
|
targets: featureTargets,
|
|
@@ -3035,11 +3127,12 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3035
3127
|
gpuWork: featureGpuWork,
|
|
3036
3128
|
});
|
|
3037
3129
|
lastVisibilityStats.explicitlyHidden = featureFrame.hiddenEntityReports.length;
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3130
|
+
reportPendingRenderFeatureErrors(
|
|
3131
|
+
featureFrame.errors,
|
|
3132
|
+
frameState.frameNumber,
|
|
3133
|
+
pendingFeatureErrorLastReportedFrame,
|
|
3134
|
+
internals.errorRegistry,
|
|
3135
|
+
);
|
|
3043
3136
|
const postProcessParamsCandidate = preparePostProcessParamsResources(
|
|
3044
3137
|
featureFrame.fullscreenEffects,
|
|
3045
3138
|
);
|
|
@@ -3172,7 +3265,8 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3172
3265
|
}
|
|
3173
3266
|
return runProfiledRenderPhase(profileSession, phase, action);
|
|
3174
3267
|
};
|
|
3175
|
-
|
|
3268
|
+
const bloomAdmitted = standardBloomAdmitted(cameras[0]);
|
|
3269
|
+
if (bloomAdmitted) {
|
|
3176
3270
|
internals.getPipelineState()?.perPassResources.ensureBloomResources?.();
|
|
3177
3271
|
}
|
|
3178
3272
|
const liveOutput = cameras[0]?.output;
|
|
@@ -3226,6 +3320,10 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3226
3320
|
activeEntityKeys: visibilityProjection.activeEntityKeys,
|
|
3227
3321
|
activeEntityRevision: visibilityProjection.activeEntityRevision,
|
|
3228
3322
|
telemetryCandidateCount: lodCandidateCountForFrame,
|
|
3323
|
+
telemetrySubmit: {
|
|
3324
|
+
frameId: lodSubmitFrameId,
|
|
3325
|
+
deviceGeneration: internals.deviceScope.generation,
|
|
3326
|
+
},
|
|
3229
3327
|
...(occlusionProjection === undefined ? {} : { occlusion: occlusionProjection }),
|
|
3230
3328
|
},
|
|
3231
3329
|
compositionLeases,
|
|
@@ -3254,6 +3352,9 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3254
3352
|
undefined,
|
|
3255
3353
|
ssrDependencies,
|
|
3256
3354
|
dynamicGeometryFrames.onRenderableDraw(compositionWorlds),
|
|
3355
|
+
environment?.fog,
|
|
3356
|
+
opts.sampleTimeSeconds,
|
|
3357
|
+
opts.temporalReset === true,
|
|
3257
3358
|
),
|
|
3258
3359
|
);
|
|
3259
3360
|
dynamicGeometryFrames.commit(submitted);
|
|
@@ -3341,7 +3442,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3341
3442
|
frameState.depthOfFieldLastSubmitFailed = true;
|
|
3342
3443
|
}
|
|
3343
3444
|
internals.getPipelineState()?.perPassResources.commitBloomResources?.();
|
|
3344
|
-
const nextBloom =
|
|
3445
|
+
const nextBloom = bloomAdmitted ? 'on' : 'off';
|
|
3345
3446
|
if (frameState.lastSuccessfulBloom === 'on' && nextBloom !== 'on') {
|
|
3346
3447
|
internals
|
|
3347
3448
|
.getPipelineState()
|
|
@@ -3406,6 +3507,7 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3406
3507
|
}),
|
|
3407
3508
|
);
|
|
3408
3509
|
} finally {
|
|
3510
|
+
if (!submitted) persistentRenderScene.discardTemporalFrame();
|
|
3409
3511
|
internals.recoveryColdWorkGuard?.endFrame();
|
|
3410
3512
|
if (ownsProfileFrame) {
|
|
3411
3513
|
try {
|
|
@@ -3424,13 +3526,46 @@ export function createRenderSystem(internals: RenderSystemInternals): RenderSyst
|
|
|
3424
3526
|
const currentFrameId = frameState.frameNumber - 1;
|
|
3425
3527
|
return observeCurrentFrame(options, frameState.currentFrameObservationSource, currentFrameId);
|
|
3426
3528
|
},
|
|
3427
|
-
async observeLodOcclusion(
|
|
3529
|
+
async observeLodOcclusion(receipt?: {
|
|
3530
|
+
readonly frameId: number;
|
|
3531
|
+
readonly deviceGeneration: number;
|
|
3532
|
+
}): Promise<void> {
|
|
3533
|
+
const capturedInspection = lastLodOcclusionInspection;
|
|
3534
|
+
const capturedWorldAttachments = lastLodWorldAttachments;
|
|
3535
|
+
if (capturedInspection === undefined) return;
|
|
3536
|
+
if (
|
|
3537
|
+
receipt !== undefined &&
|
|
3538
|
+
(capturedInspection.submit.frameId !== receipt.frameId ||
|
|
3539
|
+
capturedInspection.submit.deviceGeneration !== receipt.deviceGeneration)
|
|
3540
|
+
)
|
|
3541
|
+
return;
|
|
3428
3542
|
await ensureOcclusionRuntime().waitForCompletions();
|
|
3429
|
-
|
|
3430
|
-
|
|
3543
|
+
if (lastLodOcclusionInspection !== capturedInspection) return;
|
|
3544
|
+
const selection = await gpuDrivenProduction.readLodSelection();
|
|
3545
|
+
if (lastLodOcclusionInspection !== capturedInspection || selection === undefined) return;
|
|
3546
|
+
if (
|
|
3547
|
+
selection.submit !== undefined &&
|
|
3548
|
+
(selection.submit.frameId !== capturedInspection.submit.frameId ||
|
|
3549
|
+
selection.submit.deviceGeneration !== capturedInspection.submit.deviceGeneration)
|
|
3550
|
+
)
|
|
3551
|
+
return;
|
|
3552
|
+
if (
|
|
3553
|
+
receipt !== undefined &&
|
|
3554
|
+
(selection.submit === undefined ||
|
|
3555
|
+
selection.submit.frameId !== receipt.frameId ||
|
|
3556
|
+
selection.submit.deviceGeneration !== receipt.deviceGeneration)
|
|
3557
|
+
)
|
|
3558
|
+
return;
|
|
3559
|
+
applyLodSelectionTelemetry(selection, capturedInspection, capturedWorldAttachments);
|
|
3560
|
+
const published = lastLodOcclusionInspection;
|
|
3561
|
+
if (
|
|
3562
|
+
published !== undefined &&
|
|
3563
|
+
published.submit.frameId === capturedInspection.submit.frameId &&
|
|
3564
|
+
published.submit.deviceGeneration === capturedInspection.submit.deviceGeneration
|
|
3565
|
+
) {
|
|
3431
3566
|
const queryLatency = ensureOcclusionRuntime().inspectQueryLatency();
|
|
3432
3567
|
lastLodOcclusionInspection = inspectLodOcclusion({
|
|
3433
|
-
...
|
|
3568
|
+
...published,
|
|
3434
3569
|
queryLatencyUs: {
|
|
3435
3570
|
median: queryLatency.median,
|
|
3436
3571
|
p95: queryLatency.p95,
|