@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
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import type { RenderResourceScope } from '../publication/resource-scope';
|
|
2
|
+
import { resolveSpriteInstancesBuffer } from './sprite-instance-buffer';
|
|
1
3
|
// @forgeax/engine-runtime - RenderSystem record stage: main-pass sprite draws.
|
|
2
4
|
// feat-20260704 M5/w31: further-split from main-pass.ts (AC-05 <=1500 lines/file).
|
|
3
5
|
// recordSpritePass + sprite entity/transparent/instance-buffer helpers, moved verbatim.
|
|
4
6
|
|
|
5
|
-
import type { World } from '@forgeax/engine-ecs';
|
|
6
7
|
import {
|
|
7
8
|
type BindGroup,
|
|
8
9
|
type Buffer,
|
|
@@ -21,11 +22,7 @@ import type { InstanceBufferCacheEntry } from '../instance-buffer-cache';
|
|
|
21
22
|
import { SPRITE_PREMULTIPLIED_ALPHA_BLEND } from '../materials';
|
|
22
23
|
import { SPRITE_PASS_PER_INSTANCE_REGION_VARIANT_SET } from '../pbr-pipeline';
|
|
23
24
|
import { buildBeginRenderPassDescriptor, standardTopologyVariantSet } from '../pipeline-spec';
|
|
24
|
-
import type {
|
|
25
|
-
DispatchEntry,
|
|
26
|
-
MaterialSnapshot,
|
|
27
|
-
SpriteInstancesSnapshot,
|
|
28
|
-
} from '../render-system-extract';
|
|
25
|
+
import type { DispatchEntry, MaterialSnapshot } from '../render-system-extract';
|
|
29
26
|
import { resolveFoldInstanceBuffer } from './fold-instance-buffer';
|
|
30
27
|
import { worldEntityKey } from './frame-snapshot';
|
|
31
28
|
import { recordGeometryDraws, resolveGeometryInstancesBindGroup } from './main-pass-geometry';
|
|
@@ -37,55 +34,6 @@ import {
|
|
|
37
34
|
import type { _InternalRenderPipelineContext } from './render-context';
|
|
38
35
|
import { MATERIAL_PER_ENTITY_STRIDE } from './render-context';
|
|
39
36
|
|
|
40
|
-
export type { SpriteInstancesSnapshot };
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Build the interleaved sprite instance payload consumed by this record owner.
|
|
44
|
-
* The extract stage validates the two packed arrays before they reach this
|
|
45
|
-
* function, so the record path has one source of count-mismatch errors.
|
|
46
|
-
*/
|
|
47
|
-
export function interleaveSpriteInstanceBuffer(
|
|
48
|
-
transforms: Float32Array,
|
|
49
|
-
regions: Float32Array,
|
|
50
|
-
includePrevious = false,
|
|
51
|
-
): Float32Array {
|
|
52
|
-
const count = transforms.length / 16;
|
|
53
|
-
const stride = includePrevious ? 36 : 20;
|
|
54
|
-
const regionOffset = includePrevious ? 32 : 16;
|
|
55
|
-
const out = new Float32Array(count * stride);
|
|
56
|
-
for (let i = 0; i < count; i++) {
|
|
57
|
-
const dstBase = i * stride;
|
|
58
|
-
const transformBase = i * 16;
|
|
59
|
-
const regionBase = i * 4;
|
|
60
|
-
for (let k = 0; k < 16; k++) out[dstBase + k] = transforms[transformBase + k] ?? 0;
|
|
61
|
-
if (includePrevious) {
|
|
62
|
-
for (let k = 0; k < 16; k++) {
|
|
63
|
-
out[dstBase + 16 + k] = transforms[transformBase + k] ?? 0;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
for (let k = 0; k < 4; k++) {
|
|
67
|
-
out[dstBase + regionOffset + k] = regions[regionBase + k] ?? 0;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
return out;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Check whether the existing per-entity sprite buffer still matches the
|
|
75
|
-
* extract snapshot and interleaved byte count.
|
|
76
|
-
*/
|
|
77
|
-
export function spriteInstancesCacheHit(
|
|
78
|
-
entry: InstanceBufferCacheEntry | undefined,
|
|
79
|
-
snapshot: SpriteInstancesSnapshot,
|
|
80
|
-
requestedBytes: number,
|
|
81
|
-
): boolean {
|
|
82
|
-
return (
|
|
83
|
-
entry !== undefined &&
|
|
84
|
-
entry.uploadedArchVersion === snapshot.archVersion &&
|
|
85
|
-
entry.uploadedByteLength === requestedBytes
|
|
86
|
-
);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
37
|
/**
|
|
90
38
|
* Decide whether the LDR record needs the transparent sprite sub-pass. This
|
|
91
39
|
* remains beside the sprite record owner so the frame stage and draw stage
|
|
@@ -144,7 +92,7 @@ export function recordSpritePass(
|
|
|
144
92
|
materialSlot: number,
|
|
145
93
|
submeshMaterial: MaterialSnapshot,
|
|
146
94
|
entityKey: number,
|
|
147
|
-
materialWorld:
|
|
95
|
+
materialWorld: RenderResourceScope,
|
|
148
96
|
materialShaderId?: string,
|
|
149
97
|
) => BindGroup,
|
|
150
98
|
graphPass?: RhiRenderPassEncoder,
|
|
@@ -382,7 +330,7 @@ function recordSpriteTransparentPbrDraws(
|
|
|
382
330
|
slot: number,
|
|
383
331
|
material: MaterialSnapshot,
|
|
384
332
|
entityKey: number,
|
|
385
|
-
world:
|
|
333
|
+
world: RenderResourceScope,
|
|
386
334
|
shader?: string,
|
|
387
335
|
) => BindGroup,
|
|
388
336
|
meshGroup2: BindGroup | null,
|
|
@@ -455,7 +403,7 @@ function recordSpriteEntityDraws(
|
|
|
455
403
|
materialSlot: number,
|
|
456
404
|
material: MaterialSnapshot,
|
|
457
405
|
entityKey: number,
|
|
458
|
-
materialWorld:
|
|
406
|
+
materialWorld: RenderResourceScope,
|
|
459
407
|
) => BindGroup,
|
|
460
408
|
spritePH: RenderPipeline | null,
|
|
461
409
|
spritePH_withRegion: RenderPipeline | null,
|
|
@@ -760,100 +708,6 @@ function recordSpriteEntityDraws(
|
|
|
760
708
|
}
|
|
761
709
|
}
|
|
762
710
|
|
|
763
|
-
/**
|
|
764
|
-
* feat-20260704 M3/w19: resolve the interleaved SpriteInstances (@group(3))
|
|
765
|
-
* buffer + instanceCount for a sprite entity in the LDR blend sub-pass,
|
|
766
|
-
* extracted verbatim from recordSpriteEntityDraws. Uploads the interleaved
|
|
767
|
-
* mat4 + per-instance UV region transforms (cache-keyed on the snapshot); on
|
|
768
|
-
* over-cap fires the structured limit-exceeded error and leaves the passed-in
|
|
769
|
-
* fallback buffer/count. Returns the resolved (or unchanged) buffer + count.
|
|
770
|
-
*
|
|
771
|
-
* @internal
|
|
772
|
-
*/
|
|
773
|
-
function resolveSpriteInstancesBuffer(
|
|
774
|
-
c: _InternalRenderPipelineContext,
|
|
775
|
-
spriteEntry: _InternalRenderPipelineContext['validatedOrdered'][number],
|
|
776
|
-
fallbackBuffer: Buffer,
|
|
777
|
-
fallbackCount: number,
|
|
778
|
-
): { buffer: Buffer; count: number } {
|
|
779
|
-
const { runtime, frameState } = c;
|
|
780
|
-
let buffer = fallbackBuffer;
|
|
781
|
-
let count = fallbackCount;
|
|
782
|
-
const spriteInstancesSnap: SpriteInstancesSnapshot | undefined =
|
|
783
|
-
spriteEntry.source.spriteInstances;
|
|
784
|
-
if (spriteInstancesSnap !== undefined) {
|
|
785
|
-
const uniformFallback = runtime.device.caps.storageBuffer === false;
|
|
786
|
-
const interleaved = interleaveSpriteInstanceBuffer(
|
|
787
|
-
spriteInstancesSnap.transforms,
|
|
788
|
-
spriteInstancesSnap.regions,
|
|
789
|
-
!uniformFallback,
|
|
790
|
-
);
|
|
791
|
-
const requestedBytes = interleaved.byteLength;
|
|
792
|
-
const cap = runtime.device.limits.maxStorageBufferBindingSize;
|
|
793
|
-
if (typeof cap === 'number' && requestedBytes > cap) {
|
|
794
|
-
runtime.errorRegistry.fire(
|
|
795
|
-
new RhiError({
|
|
796
|
-
code: 'limit-exceeded',
|
|
797
|
-
expected: `requestedBytes (${requestedBytes}) <= maxStorageBufferBindingSize (${cap})`,
|
|
798
|
-
hint: 'reduce SpriteInstances instance count to fit within device.limits.maxStorageBufferBindingSize (144 bytes per instance: current mat4 64B + previous mat4 64B + region 16B)',
|
|
799
|
-
detail: {
|
|
800
|
-
maxStorageBufferBindingSize: cap,
|
|
801
|
-
requestedBytes,
|
|
802
|
-
},
|
|
803
|
-
}),
|
|
804
|
-
);
|
|
805
|
-
} else {
|
|
806
|
-
const cachedSpriteInst = frameState.instanceBuffers.get(
|
|
807
|
-
worldEntityKey(spriteEntry.source.worldId, spriteInstancesSnap.cacheKey),
|
|
808
|
-
);
|
|
809
|
-
let activeSpriteInst: InstanceBufferCacheEntry | null = null;
|
|
810
|
-
if (spriteInstancesCacheHit(cachedSpriteInst, spriteInstancesSnap, requestedBytes)) {
|
|
811
|
-
activeSpriteInst = cachedSpriteInst ?? null;
|
|
812
|
-
} else if (requestedBytes > 0) {
|
|
813
|
-
const bufRes = runtime.device.createBuffer({
|
|
814
|
-
size: requestedBytes,
|
|
815
|
-
usage:
|
|
816
|
-
(uniformFallback ? GPU_BUFFER_USAGE_UNIFORM : GPU_BUFFER_USAGE_STORAGE) |
|
|
817
|
-
GPU_BUFFER_USAGE_COPY_DST,
|
|
818
|
-
mappedAtCreation: false,
|
|
819
|
-
});
|
|
820
|
-
if (!bufRes.ok) {
|
|
821
|
-
runtime.errorRegistry.fire(bufRes.error);
|
|
822
|
-
} else {
|
|
823
|
-
if (cachedSpriteInst !== undefined && !cachedSpriteInst.buffer.isDestroyed) {
|
|
824
|
-
const r = cachedSpriteInst.buffer.destroy();
|
|
825
|
-
if (!r.ok) runtime.errorRegistry.fire(r.error);
|
|
826
|
-
}
|
|
827
|
-
const newBuf = new GpuBuffer(runtime.device, bufRes.value);
|
|
828
|
-
activeSpriteInst = {
|
|
829
|
-
buffer: newBuf,
|
|
830
|
-
uploadedArchVersion: spriteInstancesSnap.archVersion,
|
|
831
|
-
uploadedByteLength: requestedBytes,
|
|
832
|
-
};
|
|
833
|
-
frameState.instanceBuffers.set(
|
|
834
|
-
worldEntityKey(spriteEntry.source.worldId, spriteInstancesSnap.cacheKey),
|
|
835
|
-
activeSpriteInst,
|
|
836
|
-
);
|
|
837
|
-
}
|
|
838
|
-
}
|
|
839
|
-
if (activeSpriteInst !== null && requestedBytes > 0) {
|
|
840
|
-
const writeRes = runtime.device.queue.writeBuffer(
|
|
841
|
-
activeSpriteInst.buffer.handle,
|
|
842
|
-
0,
|
|
843
|
-
interleaved,
|
|
844
|
-
);
|
|
845
|
-
if (!writeRes.ok) {
|
|
846
|
-
runtime.errorRegistry.fire(writeRes.error);
|
|
847
|
-
} else {
|
|
848
|
-
buffer = activeSpriteInst.buffer.handle;
|
|
849
|
-
count = spriteInstancesSnap.instanceCount;
|
|
850
|
-
}
|
|
851
|
-
}
|
|
852
|
-
}
|
|
853
|
-
}
|
|
854
|
-
return { buffer, count };
|
|
855
|
-
}
|
|
856
|
-
|
|
857
711
|
function transparentPassColorFormat(
|
|
858
712
|
c: _InternalRenderPipelineContext,
|
|
859
713
|
pipelineState: _InternalRenderPipelineContext['pipelineState'] = c.pipelineState,
|
package/src/record/main-pass.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { World } from '@forgeax/engine-ecs';
|
|
2
1
|
import { probeVideoHighPerfUpload } from '@forgeax/engine-graphics-extras';
|
|
3
2
|
import type { GraphResourceResolver } from '@forgeax/engine-render-graph';
|
|
4
3
|
import {
|
|
@@ -19,6 +18,7 @@ import { getOrCreateIblCache } from '../ibl/IblPipelineCache';
|
|
|
19
18
|
import type { SkylightBindGroupResources } from '../ibl/skylight-bind-group';
|
|
20
19
|
import { buildBeginRenderPassDescriptor, standardTopologyBindGroupReady } from '../pipeline-spec';
|
|
21
20
|
import { POINTS_LINES_MATERIAL_SHADER_ID } from '../points-lines/record';
|
|
21
|
+
import type { RenderResourceScope } from '../publication/resource-scope';
|
|
22
22
|
import type { ReflectionProbeSelectionResult } from '../reflection/projection';
|
|
23
23
|
import type { RenderRecordPhase } from '../render-contract';
|
|
24
24
|
import type {
|
|
@@ -529,7 +529,7 @@ export function recordMainPass(
|
|
|
529
529
|
identities: [
|
|
530
530
|
getOpaqueResourceIdentity(skylightResources.irradianceSampler as object),
|
|
531
531
|
getOpaqueResourceIdentity(skylightResources.prefilterSampler as object),
|
|
532
|
-
getOpaqueResourceIdentity(skylightResources.
|
|
532
|
+
getOpaqueResourceIdentity(skylightResources.irradianceSampler as object),
|
|
533
533
|
],
|
|
534
534
|
},
|
|
535
535
|
resources: {
|
|
@@ -549,7 +549,9 @@ export function recordMainPass(
|
|
|
549
549
|
},
|
|
550
550
|
brdfLut: {
|
|
551
551
|
viewIdentity: getOpaqueResourceIdentity(skylightResources.brdfLutView as object),
|
|
552
|
-
samplerIdentity: getOpaqueResourceIdentity(
|
|
552
|
+
samplerIdentity: getOpaqueResourceIdentity(
|
|
553
|
+
skylightResources.irradianceSampler as object,
|
|
554
|
+
),
|
|
553
555
|
deviceGeneration: runtime.deviceScope.generation,
|
|
554
556
|
},
|
|
555
557
|
intensityBufferIdentity: getOpaqueResourceIdentity(
|
|
@@ -590,7 +592,7 @@ export function recordMainPass(
|
|
|
590
592
|
// which cannot render a PBR decal). Captures only frame-stable closure
|
|
591
593
|
// state; the caller passes the per-submesh material snapshot + entityKey
|
|
592
594
|
// (for video texture routing) and sets the dynamic UBO offset itself.
|
|
593
|
-
// Selection keys use the extracted frame index, never
|
|
595
|
+
// Selection keys use the extracted frame index, never RenderResourceScope.identity.
|
|
594
596
|
const hasProbeBindings = (c.reflectionProbes?.table.rows.length ?? 0) > 0;
|
|
595
597
|
const worldIndices = hasProbeBindings
|
|
596
598
|
? new Map(
|
|
@@ -632,7 +634,6 @@ export function recordMainPass(
|
|
|
632
634
|
skylightPrefilterView: skylightResources.prefilterView,
|
|
633
635
|
prefilterSampler: row.sampler,
|
|
634
636
|
brdfLutView: skylightResources.brdfLutView,
|
|
635
|
-
brdfLutSampler: skylightResources.brdfLutSampler,
|
|
636
637
|
intensityBuffer: row.uniformBuffer,
|
|
637
638
|
};
|
|
638
639
|
return { resources: probeResources, probeIndex: row.index };
|
|
@@ -657,7 +658,7 @@ export function recordMainPass(
|
|
|
657
658
|
const buildPerSubmeshMaterialBg = (
|
|
658
659
|
submeshMaterial: MaterialSnapshot,
|
|
659
660
|
entityKey: number,
|
|
660
|
-
materialWorld:
|
|
661
|
+
materialWorld: RenderResourceScope = world,
|
|
661
662
|
materialShaderId: string | undefined = submeshMaterial.materialShaderId,
|
|
662
663
|
): BindGroup =>
|
|
663
664
|
buildPerSubmeshMaterialBgImpl(
|
|
@@ -748,7 +749,7 @@ export function recordMainPass(
|
|
|
748
749
|
materialSlot: number,
|
|
749
750
|
material: MaterialSnapshot,
|
|
750
751
|
entityKey: number,
|
|
751
|
-
materialWorld:
|
|
752
|
+
materialWorld: RenderResourceScope = world,
|
|
752
753
|
materialShaderId: string | undefined = material.materialShaderId,
|
|
753
754
|
): BindGroup =>
|
|
754
755
|
!hasProbeBindings &&
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { resolveAssetHandle } from '@forgeax/engine-assets-runtime';
|
|
2
|
-
import type { World } from '@forgeax/engine-ecs';
|
|
3
2
|
import type { BindGroupEntry, BindGroupLayout, Buffer } from '@forgeax/engine-rhi';
|
|
4
3
|
import { err, ok } from '@forgeax/engine-rhi';
|
|
5
4
|
import {
|
|
@@ -14,6 +13,8 @@ import { transmissionBackdropAvailable } from '../assembly/device-feature-admiss
|
|
|
14
13
|
import { GPU_BUFFER_USAGE_COPY_DST, GPU_BUFFER_USAGE_UNIFORM } from '../gpu-usage';
|
|
15
14
|
import type { SkylightBindGroupResources } from '../ibl/skylight-bind-group';
|
|
16
15
|
import { assembleMaterialWithSkylightEntries } from '../ibl/skylight-bind-group';
|
|
16
|
+
import type { RenderResourceScope } from '../publication/resource-scope';
|
|
17
|
+
import { renderAssetByGuid } from '../publication/resource-scope';
|
|
17
18
|
import {
|
|
18
19
|
applyParamSchemaDefaultsToUbo,
|
|
19
20
|
applyParamSnapshotToUbo,
|
|
@@ -28,7 +29,7 @@ export type PreparedResolverCaches = {
|
|
|
28
29
|
readonly preparedGroup0Pipelines: WeakSet<object>;
|
|
29
30
|
readonly preparedViewOnlyPipelines: WeakSet<object>;
|
|
30
31
|
readonly preparedRenderMaterialPipelines: WeakSet<object>;
|
|
31
|
-
readonly preparedAssetHandles: WeakMap<
|
|
32
|
+
readonly preparedAssetHandles: WeakMap<RenderResourceScope, Map<string, number>>;
|
|
32
33
|
};
|
|
33
34
|
|
|
34
35
|
export function createPreparedResolverCaches(): PreparedResolverCaches {
|
|
@@ -45,7 +46,7 @@ export function createPreparedResolverCaches(): PreparedResolverCaches {
|
|
|
45
46
|
function preparedHandle<Brand extends string>(
|
|
46
47
|
runtime: RenderSystemInternals,
|
|
47
48
|
caches: PreparedResolverCaches,
|
|
48
|
-
world:
|
|
49
|
+
world: RenderResourceScope,
|
|
49
50
|
guid: string,
|
|
50
51
|
brand: Brand,
|
|
51
52
|
): Handle<Brand, 'shared'> | undefined {
|
|
@@ -57,6 +58,8 @@ function preparedHandle<Brand extends string>(
|
|
|
57
58
|
const key = `${brand}:${guid.toLowerCase()}`;
|
|
58
59
|
const cached = handles.get(key);
|
|
59
60
|
if (cached !== undefined) return cached as Handle<Brand, 'shared'>;
|
|
61
|
+
if ('resolveAsset' in world)
|
|
62
|
+
return world.handleForGuid(guid) as Handle<Brand, 'shared'> | undefined;
|
|
60
63
|
const asset = runtime.assets.lookup(guid);
|
|
61
64
|
if (asset === undefined) return undefined;
|
|
62
65
|
const handle = world.allocSharedRef(brand, asset);
|
|
@@ -67,7 +70,7 @@ function preparedHandle<Brand extends string>(
|
|
|
67
70
|
export function preparedMaterialBindings(
|
|
68
71
|
runtime: RenderSystemInternals,
|
|
69
72
|
caches: PreparedResolverCaches,
|
|
70
|
-
worlds: readonly
|
|
73
|
+
worlds: readonly RenderResourceScope[],
|
|
71
74
|
materialShaderId: string,
|
|
72
75
|
worldIndex: number,
|
|
73
76
|
materialGuid: string,
|
|
@@ -75,7 +78,10 @@ export function preparedMaterialBindings(
|
|
|
75
78
|
skylightResources?: SkylightBindGroupResources,
|
|
76
79
|
) {
|
|
77
80
|
const world = worlds[worldIndex];
|
|
78
|
-
const material =
|
|
81
|
+
const material =
|
|
82
|
+
world === undefined
|
|
83
|
+
? undefined
|
|
84
|
+
: renderAssetByGuid<MaterialAsset>(world, runtime.assets, materialGuid);
|
|
79
85
|
const pipelineState = runtime.getPipelineState();
|
|
80
86
|
if (world === undefined || material?.kind !== 'material' || pipelineState === null) {
|
|
81
87
|
return err(new Error('prepared material asset is unavailable'));
|
|
@@ -203,7 +209,6 @@ export function preparedMaterialBindings(
|
|
|
203
209
|
prefilterView: fallback.prefilterView,
|
|
204
210
|
prefilterSampler: fallback.sampler,
|
|
205
211
|
brdfLutView: fallback.brdfLutView,
|
|
206
|
-
brdfLutSampler: fallback.sampler,
|
|
207
212
|
intensityBuffer: fallback.intensityBuffer,
|
|
208
213
|
},
|
|
209
214
|
transmissionBackdropAvailable(runtime.device.limits.maxSampledTexturesPerShaderStage)
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { AssetRegistry, DynamicTextureStore } from '@forgeax/engine-assets-runtime';
|
|
2
|
-
import type { World } from '@forgeax/engine-ecs';
|
|
3
2
|
import type { VertexLayoutProjection } from '@forgeax/engine-geometry';
|
|
4
3
|
import type { Profiler } from '@forgeax/engine-profiler';
|
|
5
4
|
import type { CompiledRenderGraphInfo } from '@forgeax/engine-render-graph';
|
|
@@ -58,6 +57,7 @@ import type { StandardProfile } from '../pipeline/standard-profile';
|
|
|
58
57
|
import type { PipelineBuilderShaderModuleFactory } from '../pipeline-builder';
|
|
59
58
|
import type { PointsLinesInspection } from '../points-lines/inspection';
|
|
60
59
|
import type { PointsLinesRecordPlan } from '../points-lines/record';
|
|
60
|
+
import type { RenderResourceScope } from '../publication/resource-scope';
|
|
61
61
|
import type { ReflectionProbeTable } from '../reflection/gpu-table';
|
|
62
62
|
import type { ReflectionProbeSelectionResult } from '../reflection/projection';
|
|
63
63
|
import type { FrameObservationDomain } from '../render-contract';
|
|
@@ -582,7 +582,7 @@ export interface _StandardForwardSceneView {
|
|
|
582
582
|
readonly skybox: SkyboxSnapshot | undefined;
|
|
583
583
|
readonly profilePhase?: <T>(phase: RenderRecordPhase, action: () => T) => T;
|
|
584
584
|
readonly directionalShadowCacheReuse: boolean;
|
|
585
|
-
readonly world:
|
|
585
|
+
readonly world: RenderResourceScope;
|
|
586
586
|
readonly tonemapActive: boolean;
|
|
587
587
|
readonly geometryColorView: TextureView | null;
|
|
588
588
|
readonly geometryDepthView: TextureView | null;
|
|
@@ -1874,7 +1874,6 @@ function ensureSpotShadowMaterialBg(c: _InternalRenderPipelineContext): BindGrou
|
|
|
1874
1874
|
prefilterView: fb.prefilterView,
|
|
1875
1875
|
prefilterSampler: fb.sampler,
|
|
1876
1876
|
brdfLutView: fb.brdfLutView,
|
|
1877
|
-
brdfLutSampler: fb.sampler,
|
|
1878
1877
|
intensityBuffer: fb.intensityBuffer,
|
|
1879
1878
|
},
|
|
1880
1879
|
transmissionBackdropAvailable(runtime.device.limits.maxSampledTexturesPerShaderStage)
|
|
@@ -1956,7 +1955,6 @@ function ensureGpuDrivenAlphaMaskMaterialBg(
|
|
|
1956
1955
|
prefilterView: fallback.prefilterView,
|
|
1957
1956
|
prefilterSampler: fallback.sampler,
|
|
1958
1957
|
brdfLutView: fallback.brdfLutView,
|
|
1959
|
-
brdfLutSampler: fallback.sampler,
|
|
1960
1958
|
intensityBuffer: fallback.intensityBuffer,
|
|
1961
1959
|
} satisfies import('../ibl/skylight-bind-group').SkylightBindGroupResources;
|
|
1962
1960
|
const deps: PerSubmeshMaterialBgDeps = {
|
|
@@ -2022,7 +2020,6 @@ function ensureGpuDrivenCustomShadowMaterialBg(
|
|
|
2022
2020
|
prefilterView: fallback.prefilterView,
|
|
2023
2021
|
prefilterSampler: fallback.sampler,
|
|
2024
2022
|
brdfLutView: fallback.brdfLutView,
|
|
2025
|
-
brdfLutSampler: fallback.sampler,
|
|
2026
2023
|
intensityBuffer: fallback.intensityBuffer,
|
|
2027
2024
|
} satisfies import('../ibl/skylight-bind-group').SkylightBindGroupResources;
|
|
2028
2025
|
const deps: PerSubmeshMaterialBgDeps = {
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { type Buffer, RhiError } from '@forgeax/engine-rhi';
|
|
2
|
+
import { GpuBuffer } from '../gpu-resource';
|
|
3
|
+
import {
|
|
4
|
+
GPU_BUFFER_USAGE_COPY_DST,
|
|
5
|
+
GPU_BUFFER_USAGE_STORAGE,
|
|
6
|
+
GPU_BUFFER_USAGE_UNIFORM,
|
|
7
|
+
} from '../gpu-usage';
|
|
8
|
+
import type { InstanceBufferCacheEntry } from '../instance-buffer-cache';
|
|
9
|
+
import type { SpriteInstancesSnapshot } from '../render-system-extract';
|
|
10
|
+
import { worldEntityKey } from './frame-snapshot';
|
|
11
|
+
import type { _InternalRenderPipelineContext } from './render-context';
|
|
12
|
+
|
|
13
|
+
export type { SpriteInstancesSnapshot } from '../render-system-extract';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Build the interleaved sprite instance payload consumed by this record owner.
|
|
17
|
+
* The extract stage validates the two packed arrays before they reach this
|
|
18
|
+
* function, so the record path has one source of count-mismatch errors.
|
|
19
|
+
*/
|
|
20
|
+
export function interleaveSpriteInstanceBuffer(
|
|
21
|
+
transforms: Float32Array,
|
|
22
|
+
regions: Float32Array,
|
|
23
|
+
includePrevious = false,
|
|
24
|
+
): Float32Array {
|
|
25
|
+
const count = transforms.length / 16;
|
|
26
|
+
const stride = includePrevious ? 36 : 20;
|
|
27
|
+
const regionOffset = includePrevious ? 32 : 16;
|
|
28
|
+
const out = new Float32Array(count * stride);
|
|
29
|
+
for (let i = 0; i < count; i++) {
|
|
30
|
+
const dstBase = i * stride;
|
|
31
|
+
const transformBase = i * 16;
|
|
32
|
+
const regionBase = i * 4;
|
|
33
|
+
for (let k = 0; k < 16; k++) out[dstBase + k] = transforms[transformBase + k] ?? 0;
|
|
34
|
+
if (includePrevious) {
|
|
35
|
+
for (let k = 0; k < 16; k++) {
|
|
36
|
+
out[dstBase + 16 + k] = transforms[transformBase + k] ?? 0;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
for (let k = 0; k < 4; k++) {
|
|
40
|
+
out[dstBase + regionOffset + k] = regions[regionBase + k] ?? 0;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return out;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Check whether the existing per-entity sprite buffer still matches the
|
|
48
|
+
* extract snapshot and interleaved byte count.
|
|
49
|
+
*/
|
|
50
|
+
export function spriteInstancesCacheHit(
|
|
51
|
+
entry: InstanceBufferCacheEntry | undefined,
|
|
52
|
+
snapshot: SpriteInstancesSnapshot,
|
|
53
|
+
requestedBytes: number,
|
|
54
|
+
): boolean {
|
|
55
|
+
return (
|
|
56
|
+
entry !== undefined &&
|
|
57
|
+
entry.uploadedArchVersion === snapshot.archVersion &&
|
|
58
|
+
entry.uploadedByteLength === requestedBytes
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* feat-20260704 M3/w19: resolve the interleaved SpriteInstances (@group(3))
|
|
64
|
+
* buffer + instanceCount for a sprite entity in the LDR blend sub-pass,
|
|
65
|
+
* extracted verbatim from recordSpriteEntityDraws. Uploads the interleaved
|
|
66
|
+
* mat4 + per-instance UV region transforms (cache-keyed on the snapshot); on
|
|
67
|
+
* over-cap fires the structured limit-exceeded error and leaves the passed-in
|
|
68
|
+
* fallback buffer/count. Returns the resolved (or unchanged) buffer + count.
|
|
69
|
+
*
|
|
70
|
+
* @internal
|
|
71
|
+
*/
|
|
72
|
+
export function resolveSpriteInstancesBuffer(
|
|
73
|
+
c: Pick<_InternalRenderPipelineContext, 'runtime' | 'frameState'>,
|
|
74
|
+
spriteEntry: _InternalRenderPipelineContext['validatedOrdered'][number],
|
|
75
|
+
fallbackBuffer: Buffer,
|
|
76
|
+
fallbackCount: number,
|
|
77
|
+
): { buffer: Buffer; count: number } {
|
|
78
|
+
const { runtime, frameState } = c;
|
|
79
|
+
let buffer = fallbackBuffer;
|
|
80
|
+
let count = fallbackCount;
|
|
81
|
+
const spriteInstancesSnap: SpriteInstancesSnapshot | undefined =
|
|
82
|
+
spriteEntry.source.spriteInstances;
|
|
83
|
+
if (spriteInstancesSnap !== undefined) {
|
|
84
|
+
if (spriteInstancesSnap.instanceCount === 0) return { buffer, count: 0 };
|
|
85
|
+
const uniformFallback = runtime.device.caps.storageBuffer === false;
|
|
86
|
+
const interleaved = interleaveSpriteInstanceBuffer(
|
|
87
|
+
spriteInstancesSnap.transforms,
|
|
88
|
+
spriteInstancesSnap.regions,
|
|
89
|
+
!uniformFallback,
|
|
90
|
+
);
|
|
91
|
+
const requestedBytes = interleaved.byteLength;
|
|
92
|
+
const cap = runtime.device.limits.maxStorageBufferBindingSize;
|
|
93
|
+
if (typeof cap === 'number' && requestedBytes > cap) {
|
|
94
|
+
runtime.errorRegistry.fire(
|
|
95
|
+
new RhiError({
|
|
96
|
+
code: 'limit-exceeded',
|
|
97
|
+
expected: `requestedBytes (${requestedBytes}) <= maxStorageBufferBindingSize (${cap})`,
|
|
98
|
+
hint: 'reduce SpriteInstances instance count to fit within device.limits.maxStorageBufferBindingSize (144 bytes per instance: current mat4 64B + previous mat4 64B + region 16B)',
|
|
99
|
+
detail: {
|
|
100
|
+
maxStorageBufferBindingSize: cap,
|
|
101
|
+
requestedBytes,
|
|
102
|
+
},
|
|
103
|
+
}),
|
|
104
|
+
);
|
|
105
|
+
} else {
|
|
106
|
+
const cachedSpriteInst = frameState.instanceBuffers.get(
|
|
107
|
+
worldEntityKey(spriteEntry.source.worldId, spriteInstancesSnap.cacheKey),
|
|
108
|
+
);
|
|
109
|
+
let activeSpriteInst: InstanceBufferCacheEntry | null = null;
|
|
110
|
+
if (spriteInstancesCacheHit(cachedSpriteInst, spriteInstancesSnap, requestedBytes)) {
|
|
111
|
+
activeSpriteInst = cachedSpriteInst ?? null;
|
|
112
|
+
} else if (requestedBytes > 0) {
|
|
113
|
+
const bufRes = runtime.device.createBuffer({
|
|
114
|
+
size: requestedBytes,
|
|
115
|
+
usage:
|
|
116
|
+
(uniformFallback ? GPU_BUFFER_USAGE_UNIFORM : GPU_BUFFER_USAGE_STORAGE) |
|
|
117
|
+
GPU_BUFFER_USAGE_COPY_DST,
|
|
118
|
+
mappedAtCreation: false,
|
|
119
|
+
});
|
|
120
|
+
if (!bufRes.ok) {
|
|
121
|
+
runtime.errorRegistry.fire(bufRes.error);
|
|
122
|
+
} else {
|
|
123
|
+
if (cachedSpriteInst !== undefined && !cachedSpriteInst.buffer.isDestroyed) {
|
|
124
|
+
const r = cachedSpriteInst.buffer.destroy();
|
|
125
|
+
if (!r.ok) runtime.errorRegistry.fire(r.error);
|
|
126
|
+
}
|
|
127
|
+
const newBuf = new GpuBuffer(runtime.device, bufRes.value);
|
|
128
|
+
activeSpriteInst = {
|
|
129
|
+
buffer: newBuf,
|
|
130
|
+
uploadedArchVersion: spriteInstancesSnap.archVersion,
|
|
131
|
+
uploadedByteLength: requestedBytes,
|
|
132
|
+
};
|
|
133
|
+
frameState.instanceBuffers.set(
|
|
134
|
+
worldEntityKey(spriteEntry.source.worldId, spriteInstancesSnap.cacheKey),
|
|
135
|
+
activeSpriteInst,
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
if (activeSpriteInst !== null && requestedBytes > 0) {
|
|
140
|
+
const writeRes = runtime.device.queue.writeBuffer(
|
|
141
|
+
activeSpriteInst.buffer.handle,
|
|
142
|
+
0,
|
|
143
|
+
interleaved,
|
|
144
|
+
);
|
|
145
|
+
if (!writeRes.ok) {
|
|
146
|
+
runtime.errorRegistry.fire(writeRes.error);
|
|
147
|
+
} else {
|
|
148
|
+
buffer = activeSpriteInst.buffer.handle;
|
|
149
|
+
count = spriteInstancesSnap.instanceCount;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return { buffer, count };
|
|
155
|
+
}
|