@forgeax/engine-render 0.1.34 → 0.1.35
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 +52 -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/authoring.mjs +2 -4
- package/dist/authoring.mjs.map +1 -1
- package/dist/chunk-3XUBWRY2.mjs +1842 -0
- package/dist/chunk-3XUBWRY2.mjs.map +1 -0
- package/dist/{chunk-UI5SFODX.mjs → chunk-G6HDNGY7.mjs} +2329 -1776
- package/dist/chunk-G6HDNGY7.mjs.map +1 -0
- package/dist/{chunk-HEB564WF.mjs → chunk-LM5IE7GF.mjs} +4 -4
- package/dist/{chunk-HEB564WF.mjs.map → chunk-LM5IE7GF.mjs.map} +1 -1
- package/dist/{chunk-MKDIT2EM.mjs → chunk-LNIUIKQ7.mjs} +143 -246
- package/dist/chunk-LNIUIKQ7.mjs.map +1 -0
- package/dist/chunk-MXTWKZO4.mjs +3268 -0
- package/dist/chunk-MXTWKZO4.mjs.map +1 -0
- package/dist/{chunk-ODZWR6JQ.mjs → chunk-MZ4C7EHF.mjs} +2042 -27
- package/dist/chunk-MZ4C7EHF.mjs.map +1 -0
- package/dist/chunk-RIPAEGI6.mjs +48 -0
- package/dist/chunk-RIPAEGI6.mjs.map +1 -0
- package/dist/{chunk-OCDLEI6I.mjs → chunk-SGPUJW3F.mjs} +117 -5
- package/dist/chunk-SGPUJW3F.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 +810 -2073
- package/dist/construct-renderer.mjs.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/plan.d.ts +2 -0
- package/dist/features/plan.d.ts.map +1 -1
- package/dist/features/types.d.ts +4 -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/shadow-ownership.d.ts +3 -3
- package/dist/gpu-driven/shadow-ownership.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 +530 -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 +33 -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 +3 -3
- package/dist/record/prepared-material-bindings.d.ts.map +1 -1
- package/dist/record/render-context.d.ts +2 -2
- package/dist/record/render-context.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 -5
- 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/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__/gpu-driven-pbr.dawn.test.ts +3 -4
- 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__/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__/render-error-code-owner.test-d.ts +1 -0
- package/src/__tests__/renderer-factory-material-contract.unit.test.ts +1 -1
- 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 +89 -61
- package/src/cloud/frame-context.ts +2 -2
- 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/plan.ts +2 -0
- package/src/features/types.ts +4 -0
- package/src/glyph-text-layout-system.ts +2 -2
- package/src/gpu-driven/shadow-ownership.ts +3 -3
- 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 +11 -17
- 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 +122 -0
- package/src/publication/__tests__/programs.unit.test.ts +25 -0
- package/src/publication/__tests__/publication.integration.test.ts +370 -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 +618 -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__/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 +42 -22
- 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 +11 -6
- package/src/record/render-context.ts +2 -2
- package/src/record/shadow-pass.ts +0 -3
- 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 +6 -206
- package/src/record/view-ubo.ts +1 -1
- package/src/record/volume-params.ts +6 -6
- package/src/recovery/render-system-candidate.ts +10 -10
- package/src/render-contract.ts +6 -1
- package/src/render-system-extract-tail.ts +33 -17
- package/src/render-system-extract.ts +2 -0
- 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 -53
- 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/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
|
@@ -79,6 +79,11 @@ interface ReadbackRecord {
|
|
|
79
79
|
export interface RenderTargetHost {
|
|
80
80
|
/** The logical owner for every target lifecycle operation. */
|
|
81
81
|
readonly owner: 'renderer';
|
|
82
|
+
/** Logical descriptions for the source publication boundary; no physical state escapes. */
|
|
83
|
+
descriptions(): readonly {
|
|
84
|
+
readonly target: RenderTarget;
|
|
85
|
+
readonly descriptor: RenderTargetDescriptor;
|
|
86
|
+
}[];
|
|
82
87
|
createRenderTarget(descriptor: RenderTargetDescriptor): RenderResult<RenderTarget, RenderError>;
|
|
83
88
|
resizeRenderTarget(
|
|
84
89
|
target: RenderTarget,
|
|
@@ -231,53 +236,51 @@ function makePhysical(
|
|
|
231
236
|
const faceViews: TextureView[] = [];
|
|
232
237
|
const depthTextures: Texture[] = [];
|
|
233
238
|
const depthViews: TextureView[] = [];
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
depthViews.push(depthView.value);
|
|
280
|
-
}
|
|
239
|
+
for (let face = 0; face < layers; face += 1) {
|
|
240
|
+
const depth = device.createTexture({
|
|
241
|
+
label: `render-target.${generation}.depth.${face}`,
|
|
242
|
+
size: {
|
|
243
|
+
width: descriptor.width,
|
|
244
|
+
height: descriptor.height,
|
|
245
|
+
depthOrArrayLayers: descriptor.sampleCount === 4 ? 1 : layers,
|
|
246
|
+
},
|
|
247
|
+
mipLevelCount: 1,
|
|
248
|
+
sampleCount: descriptor.sampleCount,
|
|
249
|
+
dimension: '2d',
|
|
250
|
+
format: 'depth24plus-stencil8',
|
|
251
|
+
usage: GPU_TEXTURE_USAGE_RENDER_ATTACHMENT,
|
|
252
|
+
viewFormats: undefined,
|
|
253
|
+
textureBindingViewDimension: undefined,
|
|
254
|
+
});
|
|
255
|
+
if (!depth.ok)
|
|
256
|
+
return {
|
|
257
|
+
ok: false,
|
|
258
|
+
error: new RenderTargetOperationFailedError({
|
|
259
|
+
operation: 'create',
|
|
260
|
+
stage: 'allocation',
|
|
261
|
+
generation,
|
|
262
|
+
cause: depth.error,
|
|
263
|
+
recovery: 'retry',
|
|
264
|
+
}),
|
|
265
|
+
};
|
|
266
|
+
const depthView = device.createTextureView(depth.value, {
|
|
267
|
+
dimension: '2d',
|
|
268
|
+
baseArrayLayer: descriptor.sampleCount === 4 ? 0 : face,
|
|
269
|
+
arrayLayerCount: 1,
|
|
270
|
+
});
|
|
271
|
+
if (!depthView.ok)
|
|
272
|
+
return {
|
|
273
|
+
ok: false,
|
|
274
|
+
error: new RenderTargetOperationFailedError({
|
|
275
|
+
operation: 'create',
|
|
276
|
+
stage: 'allocation',
|
|
277
|
+
generation,
|
|
278
|
+
cause: depthView.error,
|
|
279
|
+
recovery: 'retry',
|
|
280
|
+
}),
|
|
281
|
+
};
|
|
282
|
+
depthTextures.push(depth.value);
|
|
283
|
+
depthViews.push(depthView.value);
|
|
281
284
|
}
|
|
282
285
|
if (descriptor.sampleCount === 4) {
|
|
283
286
|
for (let face = 0; face < layers; face += 1) {
|
|
@@ -405,6 +408,13 @@ export function createRenderTargetHost(options: RenderTargetHostOptions = {}): R
|
|
|
405
408
|
|
|
406
409
|
return Object.freeze({
|
|
407
410
|
owner: 'renderer' as const,
|
|
411
|
+
descriptions() {
|
|
412
|
+
return [...targets].map((target) => {
|
|
413
|
+
const state = owner.inspect(target);
|
|
414
|
+
if (!state.ok) throw state.error;
|
|
415
|
+
return { target, descriptor: state.value.candidate?.descriptor ?? state.value.descriptor };
|
|
416
|
+
});
|
|
417
|
+
},
|
|
408
418
|
createRenderTarget(
|
|
409
419
|
descriptor: RenderTargetDescriptor,
|
|
410
420
|
): RenderResult<RenderTarget, RenderError> {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { RenderPublicationError } from '../publication/contract';
|
|
1
2
|
// Public renderer facade and profile validation.
|
|
2
3
|
// This module narrows the lifetime-heavy host implementation to the stable
|
|
3
4
|
// lease/receipt contract and owns the profile/error projection helpers.
|
|
@@ -64,7 +65,8 @@ export function exposeRenderer(renderer: RendererHostImplementation): Renderer {
|
|
|
64
65
|
cause: structuredRendererCause(cause, 'renderer-event'),
|
|
65
66
|
});
|
|
66
67
|
const drawError = (cause: RhiError | RenderError): RenderError => {
|
|
67
|
-
if (cause instanceof MotionBlurValidationError
|
|
68
|
+
if (cause instanceof MotionBlurValidationError || cause instanceof RenderPublicationError)
|
|
69
|
+
return cause;
|
|
68
70
|
if (cause instanceof RendererOperationError) return cause;
|
|
69
71
|
if (cause instanceof RendererContractFailureError) {
|
|
70
72
|
return new RendererOperationError('device-operation-failed', {
|
|
@@ -1439,7 +1439,7 @@ export async function buildReadyWebGPU(
|
|
|
1439
1439
|
// instances) and the 4-slot pipeline layout in one call, throwing on each
|
|
1440
1440
|
// device.createBindGroupLayout / device.createPipelineLayout failure.
|
|
1441
1441
|
// material BGL now carries 24 entries (canonical material 0..14 + Skylight
|
|
1442
|
-
// 15..
|
|
1442
|
+
// 15..20 + transmission 21..22); authored physical maps append after the
|
|
1443
1443
|
// engine-owned injections. The pipeline layout itself stays at 4 slots, no
|
|
1444
1444
|
// @group(4) allocated (D-5 round-4 fix for the round-2 maxBindGroups=4
|
|
1445
1445
|
// BLOCKER). The standalone unlit BGL is the 15-entry user region exposed by
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
DynamicTextureStore,
|
|
7
7
|
} from '@forgeax/engine-assets-runtime';
|
|
8
8
|
import { audioLoader } from '@forgeax/engine-audio-webaudio';
|
|
9
|
-
import {
|
|
9
|
+
import type { World } from '@forgeax/engine-ecs';
|
|
10
10
|
import { createRenderReadLease, type RenderReadLease } from '@forgeax/engine-ecs/projection';
|
|
11
11
|
import {
|
|
12
12
|
DEFAULT_VERTEX_ATTRIBUTE_MAP,
|
|
@@ -21,7 +21,6 @@ import type {
|
|
|
21
21
|
RhiDevice,
|
|
22
22
|
} from '@forgeax/engine-rhi';
|
|
23
23
|
import { err, ok, RhiError, validateDrawArgs } from '@forgeax/engine-rhi';
|
|
24
|
-
import { registerPropagateTransforms } from '@forgeax/engine-scene';
|
|
25
24
|
import {
|
|
26
25
|
findVariantByKey,
|
|
27
26
|
type MaterialShaderEntry,
|
|
@@ -39,6 +38,11 @@ import type {
|
|
|
39
38
|
PrimitiveTopology,
|
|
40
39
|
VertexAttributeMap,
|
|
41
40
|
} from '@forgeax/engine-types';
|
|
41
|
+
import { type PublishedRenderFrameInput, RenderPublicationError } from '../publication/contract';
|
|
42
|
+
import { installPublicationPrograms } from '../publication/programs';
|
|
43
|
+
import { type PreparedRenderPublication, RenderPublicationReceiver } from '../publication/receiver';
|
|
44
|
+
import { RenderPublicationTargetReceiver } from '../publication/targets';
|
|
45
|
+
import { registerRenderSourceSystems } from '../scene/source-systems';
|
|
42
46
|
import { transmissionBackdropAvailable } from './device-feature-admission';
|
|
43
47
|
|
|
44
48
|
export type { MaterialShaderManifestEntry } from '@forgeax/engine-shader';
|
|
@@ -71,7 +75,6 @@ import {
|
|
|
71
75
|
type PostProcessShaderEntry,
|
|
72
76
|
postProcessShaderModuleLabel,
|
|
73
77
|
} from '../fullscreen-post-process-pass';
|
|
74
|
-
import { glyphTextLayoutSystem } from '../glyph-text-layout-system';
|
|
75
78
|
import { GPU_SHADER_STAGE_FRAGMENT, GPU_SHADER_STAGE_VERTEX } from '../gpu-stage';
|
|
76
79
|
import { type BloomInspection, emptyBloomInspection } from '../inspection-types';
|
|
77
80
|
import { DeviceScope } from '../lifecycle';
|
|
@@ -155,7 +158,6 @@ import {
|
|
|
155
158
|
import { createGpuPassTimingObservationStore, observeGpuPassTimingDisabled } from '../renderer.js';
|
|
156
159
|
import { postSpawnResolveJoints } from '../scene-instances/post-spawn-resolve-joints';
|
|
157
160
|
import type { RenderTarget } from '../targets/contracts';
|
|
158
|
-
import { tilemapChunkExtractSystem } from '../tilemap-chunk-extract-system';
|
|
159
161
|
import type { TypedFrameObservationCapture } from '../typed-render-graph-primitives';
|
|
160
162
|
import { registerAnalyticFogPostProcess } from './analytic-fog-registration';
|
|
161
163
|
import type { RhiBackendPack } from './backend-contract';
|
|
@@ -303,7 +305,6 @@ export type { WebGPUOutcome, WebGPURendererInternals } from './webgpu-renderer-c
|
|
|
303
305
|
export { disposeObservationCaptureSet } from './webgpu-renderer-observation';
|
|
304
306
|
|
|
305
307
|
/** Bundler injection and the WebGPU renderer construction entry points. */
|
|
306
|
-
let nextDerivedSystemId = 0;
|
|
307
308
|
export async function tryCreateWebGPURenderer(
|
|
308
309
|
canvas: HTMLCanvasElement | OffscreenCanvas,
|
|
309
310
|
options: RendererOptions | undefined,
|
|
@@ -315,7 +316,12 @@ export async function tryCreateWebGPURenderer(
|
|
|
315
316
|
async function makeWebGPURenderer(
|
|
316
317
|
internals: WebGPURendererInternals,
|
|
317
318
|
): Promise<RendererAssemblyImplementation> {
|
|
319
|
+
let publicationTargets: RenderPublicationTargetReceiver | undefined;
|
|
318
320
|
let disposed = false;
|
|
321
|
+
const publicationReceiver =
|
|
322
|
+
internals.options?.publicationSource === undefined
|
|
323
|
+
? undefined
|
|
324
|
+
: new RenderPublicationReceiver(internals.options.publicationSource);
|
|
319
325
|
const observeTiming = observeGpuPassTimingDisabled;
|
|
320
326
|
const frameContinuations = new Set<ContinuationTerminator>();
|
|
321
327
|
type RecoveryInspection = RenderInspection['recovery'];
|
|
@@ -584,27 +590,7 @@ async function makeWebGPURenderer(
|
|
|
584
590
|
}
|
|
585
591
|
return state.shaderInstance;
|
|
586
592
|
};
|
|
587
|
-
// D-S9: AssetRegistry instance shared with RenderSystem. RenderSystem
|
|
588
|
-
// looks up MeshFilter.assetHandle here per frame; buildReadyWebGPU step 3
|
|
589
|
-
// uploads the registry's builtin mesh geometry to GPU buffers so the
|
|
590
|
-
// RenderSystem can route MeshFilter.assetHandle to a real (vbo, ibo) pair.
|
|
591
|
-
// feat-20260527 M1 / w1: ShaderCatalog is now eager-constructed and
|
|
592
|
-
// constructor-injected into AssetRegistry (plan-strategy D-1). The
|
|
593
|
-
// ShaderCatalogDevice adapter (shared between the catalog and per-MaterialShader
|
|
594
|
-
// pipeline cache) is already available at this point.
|
|
595
593
|
const shaderCatalog = getShader();
|
|
596
|
-
// bug-20260601-hello-tonemap-material-register M1 (plan-strategy D-1):
|
|
597
|
-
// All material-shader entries are now registered from the manifest
|
|
598
|
-
// BEFORE the renderer is returned, so `register<MaterialAsset>` referencing
|
|
599
|
-
// an engine shader succeeds without waiting for `renderer.initialization`.
|
|
600
|
-
// Host-injected ImportTransport remains a constructor-only dependency.
|
|
601
|
-
// feat-20260705-runtime-tier2-decomposition M1 / w10 (D-1 / D-2): the sole
|
|
602
|
-
// production assembly point injects (a) the post-spawn hook
|
|
603
|
-
// `postSpawnResolveJoints` (auto-wire Skin.joints; D-1) and the audio
|
|
604
|
-
// catalog-entry loader. The latter stays at this assembly boundary so
|
|
605
|
-
// assets-runtime remains independent of the concrete Web Audio backend.
|
|
606
|
-
// videoLoader is wired internally from graphics-extras; the full registry has
|
|
607
|
-
// 11 engine kinds. This is the only `new AssetRegistry(...)` call in the repo.
|
|
608
594
|
const assets = new AssetRegistry(
|
|
609
595
|
shaderCatalog,
|
|
610
596
|
internals.importTransport,
|
|
@@ -735,7 +721,9 @@ async function makeWebGPURenderer(
|
|
|
735
721
|
gpuStore.configureGpuDevice(
|
|
736
722
|
internals.device,
|
|
737
723
|
packShaderFactory,
|
|
738
|
-
(world, pod) => {
|
|
724
|
+
(world, pod, source) => {
|
|
725
|
+
// The accepted equirect identity already owns this renderer-local GPU projection.
|
|
726
|
+
if ('resolveAsset' in world) return ok(source);
|
|
739
727
|
const handle = world.allocSharedRef('EquirectAsset', pod);
|
|
740
728
|
return ok(handle);
|
|
741
729
|
},
|
|
@@ -2562,7 +2550,6 @@ async function makeWebGPURenderer(
|
|
|
2562
2550
|
currentGeneration: () => activeDeviceScope.generation,
|
|
2563
2551
|
renderSystem,
|
|
2564
2552
|
});
|
|
2565
|
-
const derivedSystemNames = new Map<World, string>();
|
|
2566
2553
|
const transformReleases = new Map<World, () => void>();
|
|
2567
2554
|
const attachmentOwner = {};
|
|
2568
2555
|
let frameId = 0;
|
|
@@ -2599,6 +2586,13 @@ async function makeWebGPURenderer(
|
|
|
2599
2586
|
renderSystem.setSurfaceDynamicInput(frame);
|
|
2600
2587
|
},
|
|
2601
2588
|
attach(world: World): RenderResult<RenderWorldLease, RenderError> {
|
|
2589
|
+
if (publicationReceiver !== undefined)
|
|
2590
|
+
return err(
|
|
2591
|
+
new RenderPublicationError({
|
|
2592
|
+
reason: 'identity',
|
|
2593
|
+
subject: 'publication Renderer has no World attachment',
|
|
2594
|
+
}),
|
|
2595
|
+
);
|
|
2602
2596
|
const attached = this.attachScene(world);
|
|
2603
2597
|
if (!attached.ok) {
|
|
2604
2598
|
return err(new RendererContractFailureError('attach', attached.error.hint));
|
|
@@ -2850,23 +2844,7 @@ async function makeWebGPURenderer(
|
|
|
2850
2844
|
}
|
|
2851
2845
|
if (attachedWorlds.has(world)) return ok(undefined);
|
|
2852
2846
|
try {
|
|
2853
|
-
|
|
2854
|
-
const derivedSystemName = `renderDerived:${++nextDerivedSystemId}`;
|
|
2855
|
-
const derived = world.addSystem(Update, {
|
|
2856
|
-
name: derivedSystemName,
|
|
2857
|
-
queries: [],
|
|
2858
|
-
fn: (world) => {
|
|
2859
|
-
tilemapChunkExtractSystem(world, (guid) => assets.lookup(guid));
|
|
2860
|
-
const glyphResult = glyphTextLayoutSystem(world, gpuStore);
|
|
2861
|
-
if (!glyphResult.ok) throw glyphResult.error;
|
|
2862
|
-
},
|
|
2863
|
-
});
|
|
2864
|
-
if (!derived.ok) {
|
|
2865
|
-
releaseTransforms();
|
|
2866
|
-
throw new Error(`failed to register ${derivedSystemName}: ${derived.error.code}`);
|
|
2867
|
-
}
|
|
2868
|
-
transformReleases.set(world, releaseTransforms);
|
|
2869
|
-
derivedSystemNames.set(world, derivedSystemName);
|
|
2847
|
+
transformReleases.set(world, registerRenderSourceSystems(world, assets, gpuStore));
|
|
2870
2848
|
attachedWorlds.add(world);
|
|
2871
2849
|
return ok(undefined);
|
|
2872
2850
|
} catch (cause) {
|
|
@@ -2897,11 +2875,6 @@ async function makeWebGPURenderer(
|
|
|
2897
2875
|
}
|
|
2898
2876
|
}
|
|
2899
2877
|
renderSystem.detachScene(world);
|
|
2900
|
-
const derivedSystemName = derivedSystemNames.get(world);
|
|
2901
|
-
if (derivedSystemName !== undefined) {
|
|
2902
|
-
world.removeSystem(Update, derivedSystemName);
|
|
2903
|
-
derivedSystemNames.delete(world);
|
|
2904
|
-
}
|
|
2905
2878
|
transformReleases.get(world)?.();
|
|
2906
2879
|
transformReleases.delete(world);
|
|
2907
2880
|
},
|
|
@@ -3105,17 +3078,43 @@ async function makeWebGPURenderer(
|
|
|
3105
3078
|
: ok(result.value);
|
|
3106
3079
|
},
|
|
3107
3080
|
draw(
|
|
3108
|
-
worldsOrRequest: readonly World[] | RenderFrameInput,
|
|
3081
|
+
worldsOrRequest: readonly World[] | RenderFrameInput | PublishedRenderFrameInput,
|
|
3109
3082
|
options?: DrawOwnerOptions,
|
|
3110
3083
|
): Result<void | FrameReceipt, RhiError | RenderError> {
|
|
3111
3084
|
const isFrameRequest = !Array.isArray(worldsOrRequest);
|
|
3112
|
-
const
|
|
3085
|
+
const publicationRequest =
|
|
3086
|
+
isFrameRequest && 'publication' in worldsOrRequest
|
|
3087
|
+
? (worldsOrRequest as PublishedRenderFrameInput)
|
|
3088
|
+
: undefined;
|
|
3089
|
+
const frameRequest =
|
|
3090
|
+
isFrameRequest && publicationRequest === undefined
|
|
3091
|
+
? (worldsOrRequest as RenderFrameInput)
|
|
3092
|
+
: undefined;
|
|
3093
|
+
let publication: PreparedRenderPublication | undefined;
|
|
3094
|
+
if (publicationRequest !== undefined) {
|
|
3095
|
+
if (publicationReceiver === undefined)
|
|
3096
|
+
return err(
|
|
3097
|
+
new RenderPublicationError({
|
|
3098
|
+
reason: 'identity',
|
|
3099
|
+
subject: 'RendererOptions.publicationSource',
|
|
3100
|
+
}),
|
|
3101
|
+
);
|
|
3102
|
+
} else if (publicationReceiver !== undefined) {
|
|
3103
|
+
return err(
|
|
3104
|
+
new RenderPublicationError({
|
|
3105
|
+
reason: 'identity',
|
|
3106
|
+
subject: 'a publication-bound renderer cannot consume local World leases',
|
|
3107
|
+
}),
|
|
3108
|
+
);
|
|
3109
|
+
}
|
|
3113
3110
|
const worlds: readonly World[] =
|
|
3114
3111
|
frameRequest !== undefined
|
|
3115
3112
|
? frameRequest.leases
|
|
3116
3113
|
.map((lease) => attachedLeases.get(lease))
|
|
3117
3114
|
.filter((world): world is World => world !== undefined)
|
|
3118
|
-
:
|
|
3115
|
+
: publicationRequest === undefined
|
|
3116
|
+
? (worldsOrRequest as readonly World[])
|
|
3117
|
+
: [];
|
|
3119
3118
|
const readLeases: readonly RenderReadLease[] | undefined =
|
|
3120
3119
|
frameRequest !== undefined
|
|
3121
3120
|
? frameRequest.leases
|
|
@@ -3170,7 +3169,14 @@ async function makeWebGPURenderer(
|
|
|
3170
3169
|
? {}
|
|
3171
3170
|
: { geometryLane: frameRequest.geometryLane }),
|
|
3172
3171
|
}
|
|
3173
|
-
:
|
|
3172
|
+
: publicationRequest === undefined
|
|
3173
|
+
? (options ?? { cameraOwner: 0, resourceOwner: 0 })
|
|
3174
|
+
: {
|
|
3175
|
+
cameraOwner: 0,
|
|
3176
|
+
resourceOwner: 0,
|
|
3177
|
+
sampleTimeSeconds: publicationRequest.publication.sampleTimeSeconds,
|
|
3178
|
+
temporalReset: publicationRequest.publication.temporalReset,
|
|
3179
|
+
};
|
|
3174
3180
|
// feat-20260612-rhi-destroy-renderer-dispose-gpu-lifecycle / M5 / w21
|
|
3175
3181
|
// (plan-strategy D-1, D-8): post-dispose the renderer is dead. AI
|
|
3176
3182
|
// users observing `result.ok === false && err.code === 'rhi-not-
|
|
@@ -3246,7 +3252,8 @@ async function makeWebGPURenderer(
|
|
|
3246
3252
|
// are non-exclusive: an empty array short-circuits to empty-worlds. The
|
|
3247
3253
|
// check is defensive against JS callers passing a non-array despite the
|
|
3248
3254
|
// compile-time World[] type (red-window migration safety).
|
|
3249
|
-
const worldCount =
|
|
3255
|
+
const worldCount =
|
|
3256
|
+
publicationRequest === undefined ? (Array.isArray(worlds) ? worlds.length : 0) : 1;
|
|
3250
3257
|
if (worldCount === 0 && internals.device.caps.backendKind === 'null') {
|
|
3251
3258
|
return ok(undefined);
|
|
3252
3259
|
}
|
|
@@ -3268,12 +3275,27 @@ async function makeWebGPURenderer(
|
|
|
3268
3275
|
internals.errorRegistry,
|
|
3269
3276
|
);
|
|
3270
3277
|
if (!contextConfigured.ok) return contextConfigured;
|
|
3271
|
-
renderTargetHost.beginFrame();
|
|
3272
3278
|
// w24 — facade-level try/catch produces Result.err on unexpected throw
|
|
3273
3279
|
// (D-P6 dual-channel preserved: per-stage RhiError continues to fan out
|
|
3274
3280
|
// through onError separately; the facade Result is the synchronous
|
|
3275
3281
|
// summary AI users can ignore or branch on).
|
|
3276
3282
|
try {
|
|
3283
|
+
if (publicationRequest !== undefined && publicationReceiver !== undefined) {
|
|
3284
|
+
const accepted = publicationReceiver.accept(publicationRequest.publication);
|
|
3285
|
+
if (!accepted.ok) return accepted;
|
|
3286
|
+
publicationTargets ??= new RenderPublicationTargetReceiver(renderTargetHost);
|
|
3287
|
+
publication = {
|
|
3288
|
+
...publicationTargets.apply(accepted.value),
|
|
3289
|
+
...(publicationRequest.onFeatureSourceSubmitted === undefined
|
|
3290
|
+
? {}
|
|
3291
|
+
: {
|
|
3292
|
+
onFeatureSourceSubmitted: publicationRequest.onFeatureSourceSubmitted,
|
|
3293
|
+
}),
|
|
3294
|
+
};
|
|
3295
|
+
installPublicationPrograms(assets, publicationRequest.publication.programs);
|
|
3296
|
+
}
|
|
3297
|
+
renderTargetHost.beginFrame();
|
|
3298
|
+
|
|
3277
3299
|
const timingHost = internals as WebGPURendererInternals & {
|
|
3278
3300
|
gpuPassTimingFrameIdentity?:
|
|
3279
3301
|
| {
|
|
@@ -3311,7 +3333,13 @@ async function makeWebGPURenderer(
|
|
|
3311
3333
|
graphGeneration: 0,
|
|
3312
3334
|
};
|
|
3313
3335
|
}
|
|
3314
|
-
const submitted = renderSystem.draw(
|
|
3336
|
+
const submitted = renderSystem.draw(
|
|
3337
|
+
worlds,
|
|
3338
|
+
drawOptions,
|
|
3339
|
+
readLeases,
|
|
3340
|
+
volumeTimingCapture,
|
|
3341
|
+
publication,
|
|
3342
|
+
);
|
|
3315
3343
|
timingHost.observationFrameId = undefined;
|
|
3316
3344
|
timingHost.observationCaptureDomains = undefined;
|
|
3317
3345
|
timingHost.gpuPassTimingFrameIdentity = undefined;
|
|
@@ -3510,6 +3538,10 @@ async function makeWebGPURenderer(
|
|
|
3510
3538
|
});
|
|
3511
3539
|
internals.errorRegistry.fire(e);
|
|
3512
3540
|
return err(e);
|
|
3541
|
+
} finally {
|
|
3542
|
+
// Native video pixels have been consumed by synchronous queue copy calls.
|
|
3543
|
+
// Release them on every success/failure path, including direct publication users.
|
|
3544
|
+
publicationReceiver?.releaseVideoFrames();
|
|
3513
3545
|
}
|
|
3514
3546
|
},
|
|
3515
3547
|
async observe(
|
|
@@ -3752,6 +3784,7 @@ async function makeWebGPURenderer(
|
|
|
3752
3784
|
disposed = true;
|
|
3753
3785
|
for (const world of attachedWorlds) dynamicGeometryHost.invalidateDynamicGeometryWorld(world);
|
|
3754
3786
|
dynamicGeometry.dispose();
|
|
3787
|
+
publicationReceiver?.dispose();
|
|
3755
3788
|
for (const continuation of frameContinuations) {
|
|
3756
3789
|
continuation.terminate({ code: 'disposed' });
|
|
3757
3790
|
}
|
|
@@ -3762,11 +3795,6 @@ async function makeWebGPURenderer(
|
|
|
3762
3795
|
}
|
|
3763
3796
|
for (const world of attachedWorlds) {
|
|
3764
3797
|
try {
|
|
3765
|
-
const derivedSystemName = derivedSystemNames.get(world);
|
|
3766
|
-
if (derivedSystemName !== undefined) {
|
|
3767
|
-
world.removeSystem(Update, derivedSystemName);
|
|
3768
|
-
derivedSystemNames.delete(world);
|
|
3769
|
-
}
|
|
3770
3798
|
transformReleases.get(world)?.();
|
|
3771
3799
|
transformReleases.delete(world);
|
|
3772
3800
|
} catch (cause) {
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import type { World } from '@forgeax/engine-ecs';
|
|
2
1
|
import type { RenderFeatureFrameContext, RenderFeatureViewContext } from '../features/types';
|
|
2
|
+
import type { RenderResourceScope } from '../publication/resource-scope';
|
|
3
3
|
import type { CameraSnapshot } from '../render-contract';
|
|
4
4
|
import type { ExtractedCloudLayer } from './extract';
|
|
5
5
|
|
|
6
6
|
/** Project the stable camera/world facts consumed by the cloud feature owner. */
|
|
7
7
|
export function createCloudFeatureView(
|
|
8
8
|
camera: CameraSnapshot | undefined,
|
|
9
|
-
worlds: readonly
|
|
9
|
+
worlds: readonly RenderResourceScope[],
|
|
10
10
|
cameraOwner: number,
|
|
11
11
|
width: number,
|
|
12
12
|
height: number,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { RenderResourceScope } from '../publication/resource-scope';
|
|
1
2
|
import { type MeshResidencyLease, MeshResidencyLifetime } from './mesh-residency-lifetime';
|
|
2
3
|
// @forgeax/engine-runtime - GpuResidencyCache
|
|
3
4
|
// (feat-20260601-device/gpu-residency-extraction M1; M2 added the deriveRenderData
|
|
@@ -37,7 +38,6 @@ import {
|
|
|
37
38
|
type MipmapShaderModuleFactory,
|
|
38
39
|
prepareMipmaps,
|
|
39
40
|
} from '@forgeax/engine-assets-runtime';
|
|
40
|
-
import type { World } from '@forgeax/engine-ecs';
|
|
41
41
|
import { deriveVertexCount, type VertexLayoutProjection } from '@forgeax/engine-geometry';
|
|
42
42
|
import { halfFloat } from '@forgeax/engine-math';
|
|
43
43
|
import {
|
|
@@ -288,8 +288,9 @@ function makeImageError<C extends ImageErrorCode>(
|
|
|
288
288
|
|
|
289
289
|
/** Cube-POD register-relay injected by the wire layer (D-3). */
|
|
290
290
|
type RegisterCube = (
|
|
291
|
-
world:
|
|
291
|
+
world: RenderResourceScope,
|
|
292
292
|
pod: EquirectAsset,
|
|
293
|
+
source: Handle<'EquirectAsset', 'shared'>,
|
|
293
294
|
) => Result<Handle<'EquirectAsset', 'shared'>, AssetError>;
|
|
294
295
|
|
|
295
296
|
// feat-20260612-rhi-destroy-renderer-dispose-gpu-lifecycle / M-3 / w11:
|
|
@@ -607,16 +608,16 @@ export class GpuResidencyCache {
|
|
|
607
608
|
}
|
|
608
609
|
|
|
609
610
|
/**
|
|
610
|
-
* Compose a cache key from the raw handle slot and its owning
|
|
611
|
+
* Compose a cache key from the raw handle slot and its owning RenderResourceScope. The
|
|
611
612
|
* draw-time world index is only a position in one frame's `worlds[]`; it is
|
|
612
|
-
* not an asset identity and can be reused by a later
|
|
613
|
+
* not an asset identity and can be reused by a later RenderResourceScope. RenderResourceScope objects
|
|
613
614
|
* therefore receive a renderer-local namespace, while numeric callers keep
|
|
614
615
|
* the legacy namespace for low-level tests and built-in upload paths.
|
|
615
616
|
*/
|
|
616
|
-
private readonly worldNamespaces = new WeakMap<
|
|
617
|
+
private readonly worldNamespaces = new WeakMap<RenderResourceScope, number>();
|
|
617
618
|
private nextWorldNamespace = 1;
|
|
618
619
|
|
|
619
|
-
private worldKey(slot: number, world:
|
|
620
|
+
private worldKey(slot: number, world: RenderResourceScope | number): string | number {
|
|
620
621
|
if (typeof world === 'number') {
|
|
621
622
|
return world === 0 ? slot : world * 0x1000000 + slot;
|
|
622
623
|
}
|
|
@@ -809,7 +810,7 @@ export class GpuResidencyCache {
|
|
|
809
810
|
*/
|
|
810
811
|
evictTexture(
|
|
811
812
|
handle: Handle<'TextureAsset', 'shared'>,
|
|
812
|
-
worldId:
|
|
813
|
+
worldId: RenderResourceScope | number = 0,
|
|
813
814
|
): { freed: number; errors: RhiError[] } {
|
|
814
815
|
const id = this.worldKey(handleSlot(handle), worldId);
|
|
815
816
|
const entry = this.textureGpuHandles.get(id);
|
|
@@ -835,7 +836,7 @@ export class GpuResidencyCache {
|
|
|
835
836
|
|
|
836
837
|
evictMesh(
|
|
837
838
|
handle: Handle<'MeshAsset', 'shared'>,
|
|
838
|
-
worldId:
|
|
839
|
+
worldId: RenderResourceScope | number = 0,
|
|
839
840
|
): { freed: number; errors: RhiError[] } {
|
|
840
841
|
const id = this.worldKey(Number(handle), worldId);
|
|
841
842
|
const entry = this.meshGpuHandles.get(id);
|
|
@@ -1000,7 +1001,7 @@ export class GpuResidencyCache {
|
|
|
1000
1001
|
*/
|
|
1001
1002
|
_getTextureGpuTexture(
|
|
1002
1003
|
handle: Handle<'TextureAsset', 'shared'>,
|
|
1003
|
-
worldId:
|
|
1004
|
+
worldId: RenderResourceScope | number = 0,
|
|
1004
1005
|
): GpuTexture | undefined {
|
|
1005
1006
|
return this.textureGpuHandles.get(this.worldKey(handleSlot(handle), worldId))?.texture;
|
|
1006
1007
|
}
|
|
@@ -1011,7 +1012,7 @@ export class GpuResidencyCache {
|
|
|
1011
1012
|
*/
|
|
1012
1013
|
getTextureGpuView(
|
|
1013
1014
|
handle: Handle<'TextureAsset', 'shared'>,
|
|
1014
|
-
worldId:
|
|
1015
|
+
worldId: RenderResourceScope | number = 0,
|
|
1015
1016
|
): TextureView | undefined {
|
|
1016
1017
|
return this.textureGpuHandles.get(this.worldKey(handleSlot(handle), worldId))?.view;
|
|
1017
1018
|
}
|
|
@@ -1024,7 +1025,7 @@ export class GpuResidencyCache {
|
|
|
1024
1025
|
ensureSamplerResident(
|
|
1025
1026
|
handle: Handle<'SamplerAsset', 'shared'>,
|
|
1026
1027
|
pod: SamplerAsset,
|
|
1027
|
-
worldId:
|
|
1028
|
+
worldId: RenderResourceScope | number = 0,
|
|
1028
1029
|
): Result<Sampler, RhiError> {
|
|
1029
1030
|
const key = this.worldKey(handleSlot(handle), worldId);
|
|
1030
1031
|
const existing = this.samplerGpuHandles.get(key);
|
|
@@ -1093,7 +1094,7 @@ export class GpuResidencyCache {
|
|
|
1093
1094
|
*/
|
|
1094
1095
|
getMeshGpuHandles(
|
|
1095
1096
|
handle: Handle<'MeshAsset', 'shared'>,
|
|
1096
|
-
worldId:
|
|
1097
|
+
worldId: RenderResourceScope | number = 0,
|
|
1097
1098
|
): MeshGpuHandles | undefined {
|
|
1098
1099
|
return this.meshGpuHandles.get(this.worldKey(Number(handle), worldId));
|
|
1099
1100
|
}
|
|
@@ -1101,7 +1102,7 @@ export class GpuResidencyCache {
|
|
|
1101
1102
|
/** Candidate leases retain the concrete allocation even after cache invalidation. */
|
|
1102
1103
|
retainMeshResidency(
|
|
1103
1104
|
handle: Handle<'MeshAsset', 'shared'>,
|
|
1104
|
-
worldId:
|
|
1105
|
+
worldId: RenderResourceScope | number = 0,
|
|
1105
1106
|
): MeshResidencyLease | undefined {
|
|
1106
1107
|
const key = this.worldKey(Number(handle), worldId);
|
|
1107
1108
|
const entry = this.meshGpuHandles.get(key);
|
|
@@ -1114,7 +1115,7 @@ export class GpuResidencyCache {
|
|
|
1114
1115
|
}
|
|
1115
1116
|
|
|
1116
1117
|
/** In-place author changes immediately miss the cache; old submissions keep their allocation. */
|
|
1117
|
-
invalidateMesh(handle: number, worldId:
|
|
1118
|
+
invalidateMesh(handle: number, worldId: RenderResourceScope | number = 0): void {
|
|
1118
1119
|
const key = this.worldKey(handle, worldId);
|
|
1119
1120
|
const entry = this.meshGpuHandles.get(key);
|
|
1120
1121
|
if (entry !== undefined) this.retireMeshEntry(key, entry);
|
|
@@ -1137,18 +1138,18 @@ export class GpuResidencyCache {
|
|
|
1137
1138
|
ensureResident(
|
|
1138
1139
|
handle: Handle<'MeshAsset', 'shared'>,
|
|
1139
1140
|
pod: TypesMeshAsset,
|
|
1140
|
-
worldId?:
|
|
1141
|
+
worldId?: RenderResourceScope | number,
|
|
1141
1142
|
lodMeshes?: readonly TypesMeshAsset[],
|
|
1142
1143
|
): Result<MeshGpuHandles, RhiError | AssetError | ImageError>;
|
|
1143
1144
|
ensureResident(
|
|
1144
1145
|
handle: Handle<'TextureAsset', 'shared'>,
|
|
1145
1146
|
pod: TextureAsset,
|
|
1146
|
-
worldId?:
|
|
1147
|
+
worldId?: RenderResourceScope | number,
|
|
1147
1148
|
): Result<TextureGpuEntry, RhiError | AssetError | ImageError>;
|
|
1148
1149
|
ensureResident(
|
|
1149
1150
|
handle: Handle<'MeshAsset', 'shared'> | Handle<'TextureAsset', 'shared'>,
|
|
1150
1151
|
pod: TypesMeshAsset | TextureAsset,
|
|
1151
|
-
worldId:
|
|
1152
|
+
worldId: RenderResourceScope | number = 0,
|
|
1152
1153
|
lodMeshes: readonly TypesMeshAsset[] = [],
|
|
1153
1154
|
): Result<TextureGpuEntry | MeshGpuHandles, RhiError | AssetError | ImageError> {
|
|
1154
1155
|
const id = handleSlot(handle);
|
|
@@ -1218,17 +1219,17 @@ export class GpuResidencyCache {
|
|
|
1218
1219
|
prepareResidentForRecovery(
|
|
1219
1220
|
handle: Handle<'MeshAsset', 'shared'>,
|
|
1220
1221
|
pod: TypesMeshAsset,
|
|
1221
|
-
worldId?:
|
|
1222
|
+
worldId?: RenderResourceScope | number,
|
|
1222
1223
|
): Result<RecoveryResidencyPreparation, RhiError | AssetError | ImageError>;
|
|
1223
1224
|
prepareResidentForRecovery(
|
|
1224
1225
|
handle: Handle<'TextureAsset', 'shared'>,
|
|
1225
1226
|
pod: TextureAsset,
|
|
1226
|
-
worldId?:
|
|
1227
|
+
worldId?: RenderResourceScope | number,
|
|
1227
1228
|
): Result<RecoveryResidencyPreparation, RhiError | AssetError | ImageError>;
|
|
1228
1229
|
prepareResidentForRecovery(
|
|
1229
1230
|
handle: Handle<'MeshAsset', 'shared'> | Handle<'TextureAsset', 'shared'>,
|
|
1230
1231
|
pod: TypesMeshAsset | TextureAsset,
|
|
1231
|
-
worldId:
|
|
1232
|
+
worldId: RenderResourceScope | number = 0,
|
|
1232
1233
|
): Result<RecoveryResidencyPreparation, RhiError | AssetError | ImageError> {
|
|
1233
1234
|
const id = handleSlot(handle);
|
|
1234
1235
|
if (pod.kind === 'mesh') {
|
|
@@ -1316,7 +1317,7 @@ export class GpuResidencyCache {
|
|
|
1316
1317
|
handle: Handle<'TextureAsset', 'shared'>,
|
|
1317
1318
|
pod: TextureAsset,
|
|
1318
1319
|
decoded: DecodedImage,
|
|
1319
|
-
worldId:
|
|
1320
|
+
worldId: RenderResourceScope | number = 0,
|
|
1320
1321
|
): Promise<Result<void, AssetError | ImageError | RhiError>> {
|
|
1321
1322
|
const device = this.gpuDevice;
|
|
1322
1323
|
const projected = deriveRenderDataTexture(pod);
|
|
@@ -1392,7 +1393,7 @@ export class GpuResidencyCache {
|
|
|
1392
1393
|
pod: TextureAsset,
|
|
1393
1394
|
decoded: DecodedImage,
|
|
1394
1395
|
renderData: TextureRenderData,
|
|
1395
|
-
worldId:
|
|
1396
|
+
worldId: RenderResourceScope | number = 0,
|
|
1396
1397
|
): Result<TextureGpuEntry, AssetError | ImageError | RhiError> {
|
|
1397
1398
|
const device = this.gpuDevice;
|
|
1398
1399
|
const prepared = this.prepareTextureUpload(handle, pod, decoded, renderData);
|
|
@@ -1654,7 +1655,7 @@ export class GpuResidencyCache {
|
|
|
1654
1655
|
* retries by inferring "no entry => try again".
|
|
1655
1656
|
*/
|
|
1656
1657
|
async _uploadCubemapFromEquirect(
|
|
1657
|
-
world:
|
|
1658
|
+
world: RenderResourceScope,
|
|
1658
1659
|
sourceHandle: Handle<'EquirectAsset', 'shared'>,
|
|
1659
1660
|
sourcePod: EquirectAsset,
|
|
1660
1661
|
): Promise<Result<Handle<'EquirectAsset', 'shared'>, AssetError | RhiError>> {
|
|
@@ -1999,7 +2000,7 @@ export class GpuResidencyCache {
|
|
|
1999
2000
|
view: cubeView,
|
|
2000
2001
|
faceViews,
|
|
2001
2002
|
});
|
|
2002
|
-
const regResult = registerCube(world, cubeAsset);
|
|
2003
|
+
const regResult = registerCube(world, cubeAsset, sourceHandle);
|
|
2003
2004
|
if (!regResult.ok) return recordFailed(regResult.error);
|
|
2004
2005
|
const cubeHandle = regResult.value;
|
|
2005
2006
|
const cubeId = handleSlot(cubeHandle);
|
|
@@ -2252,7 +2253,7 @@ export class GpuResidencyCache {
|
|
|
2252
2253
|
handle: Handle<'MeshAsset', 'shared'>,
|
|
2253
2254
|
newVertices: Float32Array,
|
|
2254
2255
|
newIndices: Uint16Array,
|
|
2255
|
-
worldId:
|
|
2256
|
+
worldId: RenderResourceScope | number = 0,
|
|
2256
2257
|
submeshes?: readonly Submesh[],
|
|
2257
2258
|
): void {
|
|
2258
2259
|
const id = this.worldKey(handleSlot(handle), worldId);
|