@woosh/meep-engine 3.31.0 → 3.32.0
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/build/bundle-worker-terrain.js +1 -1
- package/package.json +1 -1
- package/src/engine/graphics3/DebugDrawSystem.d.ts.map +1 -1
- package/src/engine/graphics3/DebugDrawSystem.js +6 -2
- package/src/engine/graphics3/PathDisplaySystem.d.ts.map +1 -1
- package/src/engine/graphics3/PathDisplaySystem.js +311 -307
- package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
- package/src/shade/RENDERER_CONTRACT.md +15 -2
- package/src/shade/device/IMMEDIATE_DATA_PLAN_2026_08_28.md +5 -0
- package/src/shade/device/ShadeGPUCommandContext.d.ts +15 -2
- package/src/shade/device/ShadeGPUCommandContext.d.ts.map +1 -1
- package/src/shade/device/ShadeGPUCommandContext.js +154 -25
- package/src/shade/renderer/GraphicsContext.d.ts +9 -1
- package/src/shade/renderer/GraphicsContext.d.ts.map +1 -1
- package/src/shade/renderer/GraphicsContext.js +54 -15
- package/src/shade/renderer/Renderer.d.ts +19 -4
- package/src/shade/renderer/Renderer.d.ts.map +1 -1
- package/src/shade/renderer/Renderer.js +113 -2
- package/src/shade/renderer/animation/GPUAnimationManager.d.ts +10 -7
- package/src/shade/renderer/animation/GPUAnimationManager.d.ts.map +1 -1
- package/src/shade/renderer/animation/GPUAnimationManager.js +147 -45
- package/src/shade/renderer/buffer/GPUBufferStagingAllocator.d.ts +11 -2
- package/src/shade/renderer/buffer/GPUBufferStagingAllocator.d.ts.map +1 -1
- package/src/shade/renderer/buffer/GPUBufferStagingAllocator.js +95 -13
- package/src/shade/renderer/buffer/GPUBufferUploadAllocator.d.ts +60 -0
- package/src/shade/renderer/buffer/GPUBufferUploadAllocator.d.ts.map +1 -0
- package/src/shade/renderer/buffer/GPUBufferUploadAllocator.js +202 -0
- package/src/shade/renderer/buffer/GPUUploadBlock.d.ts +68 -0
- package/src/shade/renderer/buffer/GPUUploadBlock.d.ts.map +1 -0
- package/src/shade/renderer/buffer/GPUUploadBlock.js +97 -0
- package/src/shade/renderer/dynamic/GPUDynamicMeshRenderer.d.ts +20 -7
- package/src/shade/renderer/dynamic/GPUDynamicMeshRenderer.d.ts.map +1 -1
- package/src/shade/renderer/dynamic/GPUDynamicMeshRenderer.js +20 -7
- package/src/shade/renderer/geometry/meshlet/build/meshoptimizer/geometry_to_meshlets_meshoptimizer.d.ts +5 -0
- package/src/shade/renderer/geometry/meshlet/build/meshoptimizer/geometry_to_meshlets_meshoptimizer.d.ts.map +1 -1
- package/src/shade/renderer/geometry/meshlet/build/meshoptimizer/geometry_to_meshlets_meshoptimizer.js +19 -0
- package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +1 -1
- package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
- package/src/shade/renderer/rasterize/bucket/rasterization_has_opaque_bucket.d.ts +3 -1
- package/src/shade/renderer/rasterize/bucket/rasterization_has_opaque_bucket.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/bucket/rasterization_has_opaque_bucket.js +3 -1
- package/src/shade/renderer/rasterize/expand/bucket/mesh/shader_instances_rasterization_bucket_sort.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/expand/bucket/mesh/shader_instances_rasterization_bucket_sort.js +134 -88
- package/src/shade/renderer/rasterize/expand/bucket/meshlet/shader_meshlets_rasterization_bucket_sort.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/expand/bucket/meshlet/shader_meshlets_rasterization_bucket_sort.js +57 -26
- package/src/shade/renderer/rasterize/fast/graph_rasterize_scene_fast.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/fast/graph_rasterize_scene_fast.js +28 -20
- package/src/shade/renderer/rasterize/graph_clear_raster_targets.d.ts +38 -0
- package/src/shade/renderer/rasterize/graph_clear_raster_targets.d.ts.map +1 -0
- package/src/shade/renderer/rasterize/graph_clear_raster_targets.js +105 -0
- package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.d.ts +1 -1
- package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.js +21 -1
- package/src/shade/renderer/rasterize/standard/graph_rasterize_scene.d.ts.map +1 -1
- package/src/shade/renderer/rasterize/standard/graph_rasterize_scene.js +12 -20
- package/src/shade/renderer/shader/graph/graph_import_typed_buffer.d.ts +2 -1
- package/src/shade/renderer/shader/graph/graph_import_typed_buffer.d.ts.map +1 -1
- package/src/shade/renderer/shader/graph/graph_import_typed_buffer.js +15 -28
- package/src/core/geom/3d/atlas/atlas_bench_lib.d.ts +0 -73
- package/src/core/geom/3d/atlas/atlas_bench_lib.d.ts.map +0 -1
- package/src/engine/graphics3/terrain/GPUTerrainSplatRenderer.d.ts +0 -59
- package/src/engine/graphics3/terrain/GPUTerrainSplatRenderer.d.ts.map +0 -1
- package/src/engine/graphics3/terrain/pack_terrain_row_table.d.ts +0 -22
- package/src/engine/graphics3/terrain/pack_terrain_row_table.d.ts.map +0 -1
- package/src/engine/graphics3/terrain/shader_terrain_splat.d.ts +0 -26
- package/src/engine/graphics3/terrain/shader_terrain_splat.d.ts.map +0 -1
- package/src/shade/renderer/animation/ANIMATION_BOUND_TRACK_GROUP_STRUCT.d.ts +0 -25
- package/src/shade/renderer/animation/ANIMATION_BOUND_TRACK_GROUP_STRUCT.d.ts.map +0 -1
- package/src/shade/renderer/animation/ANIMATION_KEYFRAME_BLOCK_STRUCT.d.ts +0 -26
- package/src/shade/renderer/animation/ANIMATION_KEYFRAME_BLOCK_STRUCT.d.ts.map +0 -1
- package/src/shade/renderer/animation/ANIMATION_SKIN_JOINT_BLOCK_STRUCT.d.ts +0 -29
- package/src/shade/renderer/animation/ANIMATION_SKIN_JOINT_BLOCK_STRUCT.d.ts.map +0 -1
|
@@ -64,11 +64,11 @@ export class FluidObstacleSystem extends System<any> {
|
|
|
64
64
|
/**
|
|
65
65
|
* @param {FluidComponent} fluid
|
|
66
66
|
*/
|
|
67
|
-
static "__#
|
|
67
|
+
static "__#416@#refresh_masks"(fluid: FluidComponent): void;
|
|
68
68
|
/**
|
|
69
69
|
* @param {FluidComponent} fluid
|
|
70
70
|
*/
|
|
71
|
-
static "__#
|
|
71
|
+
static "__#416@#clear_field"(fluid: FluidComponent): void;
|
|
72
72
|
/**
|
|
73
73
|
* Mark every cell of `fluid` whose centre lies within `inflation` of the
|
|
74
74
|
* posed shape as solid. Iteration is clipped to the shape's world AABB
|
|
@@ -80,7 +80,7 @@ export class FluidObstacleSystem extends System<any> {
|
|
|
80
80
|
* @param {number} inflation world-units SDF threshold
|
|
81
81
|
* @param {Float64Array} point length-3 scratch
|
|
82
82
|
*/
|
|
83
|
-
static "__#
|
|
83
|
+
static "__#416@#voxelize"(fluid: FluidComponent, posed: PosedShape3D, aabb: Float64Array, inflation: number, point: Float64Array): void;
|
|
84
84
|
/**
|
|
85
85
|
* Write the obstacle's translation velocity onto every face of every cell
|
|
86
86
|
* it voxelized — the moving-wall boundary condition. Runs AFTER the mask
|
|
@@ -100,7 +100,7 @@ export class FluidObstacleSystem extends System<any> {
|
|
|
100
100
|
* @param {number} wvy
|
|
101
101
|
* @param {number} wvz
|
|
102
102
|
*/
|
|
103
|
-
static "__#
|
|
103
|
+
static "__#416@#stamp_wall_velocity"(fluid: FluidComponent, posed: PosedShape3D, aabb: Float64Array, inflation: number, point: Float64Array, wvx: number, wvy: number, wvz: number): void;
|
|
104
104
|
constructor();
|
|
105
105
|
dependencies: (typeof FluidObstacle)[];
|
|
106
106
|
components_used: (ResourceAccessSpecification<typeof Transform64> | ResourceAccessSpecification<typeof RigidBody> | ResourceAccessSpecification<typeof Collider> | ResourceAccessSpecification<typeof FluidComponent> | ResourceAccessSpecification<typeof FluidObstacle>)[];
|
|
@@ -398,14 +398,18 @@ class PathExtension extends RenderExtension {
|
|
|
398
398
|
}
|
|
399
399
|
|
|
400
400
|
const scene = frame.get(SceneColor);
|
|
401
|
+
const view = frame.get(ViewTextures);
|
|
401
402
|
|
|
402
|
-
|
|
403
|
+
const drawn = this.#renderer.graph_draw({
|
|
403
404
|
graph: frame.graph,
|
|
404
405
|
batch: this.#batch,
|
|
405
406
|
color: scene.color,
|
|
406
|
-
depth:
|
|
407
|
+
depth: view.depth,
|
|
407
408
|
camera: frame.view.camera.buffer
|
|
408
409
|
});
|
|
410
|
+
|
|
411
|
+
scene.color = drawn.color;
|
|
412
|
+
view.depth = drawn.depth;
|
|
409
413
|
}
|
|
410
414
|
}
|
|
411
415
|
|
|
@@ -590,6 +594,15 @@ which is what effects want. Set it and the pass writes depth instead: a solid su
|
|
|
590
594
|
build behind it has no depth ordering otherwise, and no CPU sort can give it one, because a painter's
|
|
591
595
|
order over triangles is wrong wherever two of them interpenetrate.
|
|
592
596
|
|
|
597
|
+
`graph_draw` hands back `{ color, depth }`, and an extension publishes both, as in §6. The depth is a
|
|
598
|
+
new handle when the pass wrote it. Anything reading the scene depth after you — depth of field,
|
|
599
|
+
motion blur, the NSS upscaler, the next extension — has to be given that handle; a development build
|
|
600
|
+
refuses the frame when it is not. Left `false`, the depth comes back as it went in.
|
|
601
|
+
|
|
602
|
+
That is also what decides the phase for solid content. At `AfterLighting` transparency has not run
|
|
603
|
+
yet, and it tests against the depth you published, so glass in front of the batch covers it. At
|
|
604
|
+
`AfterTransparency` the glass is already resolved into the colour, and the batch is drawn over it.
|
|
605
|
+
|
|
593
606
|
Residency is keyed on **the geometry**, not on batch membership, so a mesh that blinks off for a
|
|
594
607
|
frame or is removed and re-added keeps its buffers.
|
|
595
608
|
|
|
@@ -562,3 +562,8 @@ harness. Keeping the door open costs nothing; walking through it preemptively co
|
|
|
562
562
|
call sites are the strongest case for immediates, but the standing TODO there is a separate bug —
|
|
563
563
|
the 2025-09-13 note says the obvious fix produced garbage and was never chased down. Immediates
|
|
564
564
|
route around it for the ≤64-byte cases without explaining it.
|
|
565
|
+
Answered 2026-09-26: fixed independently. The garbage was frame-graph aliasing — a `queue.writeBuffer`
|
|
566
|
+
into a pooled buffer lands ahead of the whole submission, and a pass earlier in it had written that
|
|
567
|
+
buffer for another resource. The import now writes with `writeValueBuffer`, in order, and creates no
|
|
568
|
+
buffer per frame; `graph_import_typed_buffer.spec.js` pins both. Immediates would still drop the
|
|
569
|
+
buffer altogether for the ≤64-byte cases.
|
|
@@ -268,6 +268,8 @@ export class ShadeGPUCommandContext {
|
|
|
268
268
|
*/
|
|
269
269
|
allocateTransientValueBuffer<T>(type: WebGPUType, value: T, usage?: number | GPUBufferUsage): GPUBuffer;
|
|
270
270
|
/**
|
|
271
|
+
* Like {@link writeBuffer}, with the bytes serialised from `value` as `type` lays them out.
|
|
272
|
+
*
|
|
271
273
|
* @template T
|
|
272
274
|
* @param {GPUBuffer} buffer
|
|
273
275
|
* @param {number} buffer_offset
|
|
@@ -276,12 +278,22 @@ export class ShadeGPUCommandContext {
|
|
|
276
278
|
*/
|
|
277
279
|
writeValueBuffer<T_1>(buffer: GPUBuffer, buffer_offset: number, type: WebGPUType, value: T_1): void;
|
|
278
280
|
/**
|
|
279
|
-
*
|
|
281
|
+
* Write bytes into `buffer` at this point in the command stream: after everything recorded
|
|
282
|
+
* before this call, and before everything recorded after it.
|
|
283
|
+
*
|
|
284
|
+
* That is the difference from {@link GPUQueue#writeBuffer}, which lands ahead of the whole
|
|
285
|
+
* submission — ahead of passes recorded earlier in it that may still need the old contents. Here
|
|
286
|
+
* the bytes are staged, and a copy out of the staging is recorded in their place. Small writes
|
|
287
|
+
* are staged in this context's upload blocks, which reach the GPU with one queue write each when
|
|
288
|
+
* the context finishes, so a frame of thousands of them costs no mapping at all; writes of
|
|
289
|
+
* {@link MAPPED_UPLOAD_THRESHOLD} bytes or more go through a mapped staging buffer each, which is
|
|
290
|
+
* the faster road for bytes.
|
|
291
|
+
*
|
|
280
292
|
* @param {GPUBuffer} buffer
|
|
281
293
|
* @param {number} buffer_offset
|
|
282
294
|
* @param {ArrayBuffer} data
|
|
283
295
|
* @param {number} data_offset
|
|
284
|
-
* @param {number} size
|
|
296
|
+
* @param {number} size a multiple of 4, as for any buffer copy
|
|
285
297
|
*/
|
|
286
298
|
writeBuffer(buffer: GPUBuffer, buffer_offset: number, data: ArrayBuffer, data_offset: number, size: number): void;
|
|
287
299
|
/**
|
|
@@ -297,6 +309,7 @@ export type GraphicsContext = import("../renderer/GraphicsContext.js").GraphicsC
|
|
|
297
309
|
export type ShaderResourceSetDescriptor = import("../renderer/shader/resource/ShaderResourceSetDescriptor.js").ShaderResourceSetDescriptor;
|
|
298
310
|
export type WebGPUType = import("../renderer/shader/type/WebGPUType.js").WebGPUType;
|
|
299
311
|
export type TextureManager = import("../renderer/texture/TextureManager.js").TextureManager;
|
|
312
|
+
export type GPUUploadBlock = import("../renderer/buffer/GPUUploadBlock.js").GPUUploadBlock;
|
|
300
313
|
export type GPUFrameRecorder = import("./timing/profile/GPUFrameRecorder.js").GPUFrameRecorder;
|
|
301
314
|
import { GraphicsExecutionContext } from "./graph/GraphicsExecutionContext.js";
|
|
302
315
|
import { ShadeGPUComputePassEncoder } from "./pass/ShadeGPUComputePassEncoder.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ShadeGPUCommandContext.d.ts","sourceRoot":"","sources":["../../../../src/shade/device/ShadeGPUCommandContext.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ShadeGPUCommandContext.d.ts","sourceRoot":"","sources":["../../../../src/shade/device/ShadeGPUCommandContext.js"],"names":[],"mappings":"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"}
|
|
@@ -10,6 +10,7 @@ import { ShadeGPURenderPassEncoder } from "./pass/ShadeGPURenderPassEncoder.js";
|
|
|
10
10
|
import { ShadeGPUContextProfiler } from "./timing/ShadeGPUContextProfiler.js";
|
|
11
11
|
import { warn_limited } from "../util/warn_limited.js";
|
|
12
12
|
import { write_gpu_typed_buffer } from "../renderer/shader/type/serde/write_gpu_typed_buffer.js";
|
|
13
|
+
import { MAPPED_UPLOAD_THRESHOLD } from "../renderer/buffer/GPUBufferUploadAllocator.js";
|
|
13
14
|
import { BufferResourceDescriptor } from "./graph/BufferResourceDescriptor.js";
|
|
14
15
|
import { GraphicsExecutionContext } from "./graph/GraphicsExecutionContext.js";
|
|
15
16
|
|
|
@@ -24,6 +25,7 @@ import { GraphicsExecutionContext } from "./graph/GraphicsExecutionContext.js";
|
|
|
24
25
|
* @typedef {import("../renderer/shader/resource/ShaderResourceSetDescriptor.js").ShaderResourceSetDescriptor} ShaderResourceSetDescriptor
|
|
25
26
|
* @typedef {import("../renderer/shader/type/WebGPUType.js").WebGPUType} WebGPUType
|
|
26
27
|
* @typedef {import("../renderer/texture/TextureManager.js").TextureManager} TextureManager
|
|
28
|
+
* @typedef {import("../renderer/buffer/GPUUploadBlock.js").GPUUploadBlock} GPUUploadBlock
|
|
27
29
|
* @typedef {import("./timing/profile/GPUFrameRecorder.js").GPUFrameRecorder} GPUFrameRecorder
|
|
28
30
|
*/
|
|
29
31
|
|
|
@@ -180,6 +182,17 @@ export class ShadeGPUCommandContext {
|
|
|
180
182
|
#transient_buffers = [];
|
|
181
183
|
|
|
182
184
|
/**
|
|
185
|
+
* Upload blocks this context has written its small uploads into, the one being filled last. Sent
|
|
186
|
+
* to the GPU just before the submit, one queue write per block, and given back when the context
|
|
187
|
+
* finishes.
|
|
188
|
+
*
|
|
189
|
+
* @type {GPUUploadBlock[]}
|
|
190
|
+
*/
|
|
191
|
+
#upload_blocks = [];
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Mapped staging buffers this context's large uploads went through, one each. Given back when the
|
|
195
|
+
* context finishes, and mapped again by their pool before it hands them out anew.
|
|
183
196
|
*
|
|
184
197
|
* @type {GPUBuffer[]}
|
|
185
198
|
*/
|
|
@@ -727,6 +740,8 @@ export class ShadeGPUCommandContext {
|
|
|
727
740
|
}
|
|
728
741
|
|
|
729
742
|
/**
|
|
743
|
+
* Like {@link writeBuffer}, with the bytes serialised from `value` as `type` lays them out.
|
|
744
|
+
*
|
|
730
745
|
* @template T
|
|
731
746
|
* @param {GPUBuffer} buffer
|
|
732
747
|
* @param {number} buffer_offset
|
|
@@ -737,30 +752,48 @@ export class ShadeGPUCommandContext {
|
|
|
737
752
|
|
|
738
753
|
assert.notOk(this.#finished, 'already finished');
|
|
739
754
|
|
|
740
|
-
const gfx = this.#graphics;
|
|
741
|
-
|
|
742
755
|
const size = type.aligned_size;
|
|
743
756
|
|
|
744
|
-
|
|
757
|
+
if (size >= MAPPED_UPLOAD_THRESHOLD) {
|
|
758
|
+
const stage = this.#graphics.buffer_allocator_staging.get(size);
|
|
759
|
+
|
|
760
|
+
// recorded before it is filled, so a fill that throws still gives it back
|
|
761
|
+
this.#staging_buffers.push(stage);
|
|
745
762
|
|
|
746
|
-
|
|
763
|
+
write_gpu_typed_buffer(value, type, stage.getMappedRange(0, size), 0);
|
|
747
764
|
|
|
748
|
-
|
|
765
|
+
stage.unmap();
|
|
749
766
|
|
|
750
|
-
|
|
767
|
+
this.copyBufferToBuffer(stage, 0, buffer, buffer_offset, size);
|
|
751
768
|
|
|
752
|
-
|
|
769
|
+
return;
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
const block = this.#upload_block_with_room(size);
|
|
773
|
+
const offset = block.allocate(size);
|
|
774
|
+
|
|
775
|
+
write_gpu_typed_buffer(value, type, block.data, offset);
|
|
753
776
|
|
|
754
|
-
this.copyBufferToBuffer(
|
|
777
|
+
this.copyBufferToBuffer(block.buffer, offset, buffer, buffer_offset, size);
|
|
755
778
|
}
|
|
756
779
|
|
|
757
780
|
/**
|
|
758
|
-
*
|
|
781
|
+
* Write bytes into `buffer` at this point in the command stream: after everything recorded
|
|
782
|
+
* before this call, and before everything recorded after it.
|
|
783
|
+
*
|
|
784
|
+
* That is the difference from {@link GPUQueue#writeBuffer}, which lands ahead of the whole
|
|
785
|
+
* submission — ahead of passes recorded earlier in it that may still need the old contents. Here
|
|
786
|
+
* the bytes are staged, and a copy out of the staging is recorded in their place. Small writes
|
|
787
|
+
* are staged in this context's upload blocks, which reach the GPU with one queue write each when
|
|
788
|
+
* the context finishes, so a frame of thousands of them costs no mapping at all; writes of
|
|
789
|
+
* {@link MAPPED_UPLOAD_THRESHOLD} bytes or more go through a mapped staging buffer each, which is
|
|
790
|
+
* the faster road for bytes.
|
|
791
|
+
*
|
|
759
792
|
* @param {GPUBuffer} buffer
|
|
760
793
|
* @param {number} buffer_offset
|
|
761
794
|
* @param {ArrayBuffer} data
|
|
762
795
|
* @param {number} data_offset
|
|
763
|
-
* @param {number} size
|
|
796
|
+
* @param {number} size a multiple of 4, as for any buffer copy
|
|
764
797
|
*/
|
|
765
798
|
writeBuffer(buffer, buffer_offset, data, data_offset, size) {
|
|
766
799
|
assert.defined(buffer, 'buffer');
|
|
@@ -769,20 +802,95 @@ export class ShadeGPUCommandContext {
|
|
|
769
802
|
assert.isNonNegativeInteger(data_offset, 'data_offset');
|
|
770
803
|
assert.isNonNegativeInteger(size, 'size');
|
|
771
804
|
|
|
772
|
-
|
|
805
|
+
assert.notOk(this.#finished, 'already finished');
|
|
806
|
+
|
|
807
|
+
if (size % 4 !== 0) {
|
|
808
|
+
// Refused here rather than left to the copy, as a mapped staging buffer of this size
|
|
809
|
+
// always was: a copy moves whole 4-byte words, and one that cannot takes the context's
|
|
810
|
+
// whole submission down with it, later, without naming the write that did it.
|
|
811
|
+
throw new RangeError(`writeBuffer: size ${size} is not a multiple of 4`);
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
if (size === 0) {
|
|
815
|
+
// a copy of nothing changes nothing
|
|
816
|
+
return;
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
if (size >= MAPPED_UPLOAD_THRESHOLD) {
|
|
820
|
+
const stage = this.#graphics.buffer_allocator_staging.get(size);
|
|
773
821
|
|
|
774
|
-
|
|
822
|
+
// recorded before it is filled, so a fill that throws still gives it back
|
|
823
|
+
this.#staging_buffers.push(stage);
|
|
775
824
|
|
|
776
|
-
|
|
825
|
+
array_buffer_copy(data, data_offset, stage.getMappedRange(0, size), 0, size);
|
|
777
826
|
|
|
778
|
-
|
|
827
|
+
stage.unmap();
|
|
779
828
|
|
|
780
|
-
|
|
829
|
+
this.copyBufferToBuffer(stage, 0, buffer, buffer_offset, size);
|
|
781
830
|
|
|
782
|
-
|
|
831
|
+
return;
|
|
832
|
+
}
|
|
783
833
|
|
|
784
|
-
|
|
834
|
+
const block = this.#upload_block_with_room(size);
|
|
835
|
+
const offset = block.allocate(size);
|
|
785
836
|
|
|
837
|
+
array_buffer_copy(data, data_offset, block.data, offset, size);
|
|
838
|
+
|
|
839
|
+
this.copyBufferToBuffer(block.buffer, offset, buffer, buffer_offset, size);
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
/**
|
|
843
|
+
* The block to take the next `size` bytes of upload from: the one being filled, or a fresh one
|
|
844
|
+
* when that is full. Every write that comes here is smaller than
|
|
845
|
+
* {@link MAPPED_UPLOAD_THRESHOLD}, so any empty block holds it.
|
|
846
|
+
*
|
|
847
|
+
* A block that cannot take the next write is not revisited: what is left in it is wasted until
|
|
848
|
+
* the context finishes, which bounds the waste at one block's tail per block and keeps every
|
|
849
|
+
* write a single contiguous copy.
|
|
850
|
+
*
|
|
851
|
+
* @param {number} size
|
|
852
|
+
* @returns {GPUUploadBlock}
|
|
853
|
+
*/
|
|
854
|
+
#upload_block_with_room(size) {
|
|
855
|
+
const blocks = this.#upload_blocks;
|
|
856
|
+
const last = blocks.length - 1;
|
|
857
|
+
|
|
858
|
+
if (last >= 0 && blocks[last].fits(size)) {
|
|
859
|
+
return blocks[last];
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
const block = this.#graphics.buffer_allocator_upload.get();
|
|
863
|
+
|
|
864
|
+
blocks.push(block);
|
|
865
|
+
|
|
866
|
+
return block;
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
/**
|
|
870
|
+
* Put this context's upload blocks on the GPU: one queue write per block, of the part written.
|
|
871
|
+
*
|
|
872
|
+
* Must come immediately before the submit, and this is the whole of why a block can go back to
|
|
873
|
+
* its pool the moment its context finishes rather than when the GPU is done with it. The queue
|
|
874
|
+
* runs its operations in order, so a write issued here lands after everything submitted before
|
|
875
|
+
* this context — including the copies of any earlier context that held the same block — and
|
|
876
|
+
* before this context's own copies read it. Nothing is mapped, so nothing is waited for.
|
|
877
|
+
*
|
|
878
|
+
* A queue write lands ahead of its whole submission, which is why it goes only into a block and
|
|
879
|
+
* never into a destination: blocks come from a pool of their own that nothing aliases, while
|
|
880
|
+
* the frame graph's buffers are aliased within a submission, and a queue write into one of those
|
|
881
|
+
* would overwrite what an earlier pass in it still needs.
|
|
882
|
+
*
|
|
883
|
+
* @param {GPUQueue} queue
|
|
884
|
+
*/
|
|
885
|
+
#send_uploads(queue) {
|
|
886
|
+
const blocks = this.#upload_blocks;
|
|
887
|
+
const count = blocks.length;
|
|
888
|
+
|
|
889
|
+
for (let i = 0; i < count; i++) {
|
|
890
|
+
const block = blocks[i];
|
|
891
|
+
|
|
892
|
+
queue.writeBuffer(block.buffer, 0, block.data, 0, block.used);
|
|
893
|
+
}
|
|
786
894
|
}
|
|
787
895
|
|
|
788
896
|
#cleanup() {
|
|
@@ -802,11 +910,29 @@ export class ShadeGPUCommandContext {
|
|
|
802
910
|
|
|
803
911
|
}
|
|
804
912
|
|
|
805
|
-
//
|
|
913
|
+
// Blocks go back now rather than when the GPU is done with them — see #send_uploads.
|
|
914
|
+
const buffer_allocator_upload = this.#graphics.buffer_allocator_upload;
|
|
915
|
+
|
|
916
|
+
for (const block of this.#upload_blocks) {
|
|
917
|
+
buffer_allocator_upload.release(block);
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
this.#upload_blocks.length = 0;
|
|
921
|
+
|
|
922
|
+
// staging buffers are mapped again by their pool, which is when they are free again
|
|
806
923
|
const buffer_allocator_staging = this.#graphics.buffer_allocator_staging;
|
|
924
|
+
|
|
807
925
|
for (const staging of this.#staging_buffers) {
|
|
926
|
+
if (staging.mapState === "mapped") {
|
|
927
|
+
// a write that threw while filling it, so no copy out of it was recorded; unmapped
|
|
928
|
+
// here so its pool maps it afresh rather than handing out a range already given out
|
|
929
|
+
staging.unmap();
|
|
930
|
+
}
|
|
931
|
+
|
|
808
932
|
buffer_allocator_staging.release(staging);
|
|
809
933
|
}
|
|
934
|
+
|
|
935
|
+
this.#staging_buffers.length = 0;
|
|
810
936
|
}
|
|
811
937
|
|
|
812
938
|
/**
|
|
@@ -844,19 +970,22 @@ export class ShadeGPUCommandContext {
|
|
|
844
970
|
|
|
845
971
|
GPUCommandEncoder.finish() throws when the encoder is locked — any pass left un-end()ed
|
|
846
972
|
anywhere in the frame graph — and queue.submit throws on a malformed argument. This used
|
|
847
|
-
to be a bare sequence, so either throw skipped #cleanup() and every buffer
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
hidden behind the hang.
|
|
973
|
+
to be a bare sequence, so either throw skipped #cleanup() and every buffer the context held
|
|
974
|
+
stayed checked out of its allocator for good — then, a staging buffer per writeBuffer
|
|
975
|
+
call, which is most of the uniform traffic, every frame, until the process ran out of GPU
|
|
976
|
+
memory. onFinished never fired either, so a promise already awaiting done never woke and
|
|
977
|
+
profiling_absorbed hung with it — a recoverable encoding bug turned into an unbounded leak
|
|
978
|
+
plus a hung frame, with the original error hidden behind the hang.
|
|
854
979
|
|
|
855
980
|
The error still propagates: it is the thing that names the misplaced end().
|
|
856
981
|
*/
|
|
857
982
|
try {
|
|
858
983
|
const command_buffer = encoder.finish();
|
|
859
984
|
|
|
985
|
+
// after finish(), so a command buffer that could not be made sends nothing, and
|
|
986
|
+
// immediately before the submit, which is what makes the blocks safe to hand back
|
|
987
|
+
this.#send_uploads(queue);
|
|
988
|
+
|
|
860
989
|
queue.submit([command_buffer]);
|
|
861
990
|
} finally {
|
|
862
991
|
// cleanup allocated memory
|
|
@@ -64,10 +64,17 @@ export class GraphicsContext {
|
|
|
64
64
|
*/
|
|
65
65
|
buffer_allocator_native: GPUBufferAllocatorNative;
|
|
66
66
|
/**
|
|
67
|
-
*
|
|
67
|
+
* Mapped `MAP_WRITE` buffers, one per upload: where a {@link ShadeGPUCommandContext} sends its
|
|
68
|
+
* large writes, for which a mapping is the faster road (see `MAPPED_UPLOAD_THRESHOLD`).
|
|
68
69
|
* @type {GPUBufferStagingAllocator}
|
|
69
70
|
*/
|
|
70
71
|
buffer_allocator_staging: GPUBufferStagingAllocator;
|
|
72
|
+
/**
|
|
73
|
+
* Upload blocks for {@link ShadeGPUCommandContext}'s small writes — every uniform a pass is
|
|
74
|
+
* handed by value among them. Sent with one queue write per block, not mapped.
|
|
75
|
+
* @type {GPUBufferUploadAllocator}
|
|
76
|
+
*/
|
|
77
|
+
buffer_allocator_upload: GPUBufferUploadAllocator;
|
|
71
78
|
/**
|
|
72
79
|
* Used to read data back from the GPU: `MAP_READ` buffers, held by the CPU across frames, which
|
|
73
80
|
* is why they cannot come from {@link buffer_allocator_main}.
|
|
@@ -142,6 +149,7 @@ import { BindGroupManager } from "./binding/BindGroupManager.js";
|
|
|
142
149
|
import { GPUBufferAllocator } from "./buffer/GPUBufferAllocator.js";
|
|
143
150
|
import { GPUBufferAllocatorNative } from "./buffer/GPUBufferAllocatorNative.js";
|
|
144
151
|
import { GPUBufferStagingAllocator } from "./buffer/GPUBufferStagingAllocator.js";
|
|
152
|
+
import { GPUBufferUploadAllocator } from "./buffer/GPUBufferUploadAllocator.js";
|
|
145
153
|
import { GPUBufferReadbackAllocator } from "./buffer/GPUBufferReadbackAllocator.js";
|
|
146
154
|
import { GPUTextureAllocator } from "./texture/GPUTextureAllocator.js";
|
|
147
155
|
import { GPUBufferContext } from "./buffer/GPUBufferContext.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GraphicsContext.d.ts","sourceRoot":"","sources":["../../../../src/shade/renderer/GraphicsContext.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"GraphicsContext.d.ts","sourceRoot":"","sources":["../../../../src/shade/renderer/GraphicsContext.js"],"names":[],"mappings":"AAmCA;IAoKI,yBAiCC;IApMD;;OAEG;IACH,YAFU,kBAAkB,CAEjB;IAEX;;OAEG;IACH,WAFU,kBAAkB,CAElB;IAOV;;OAEG;IACH,UAFU,iBAAiB,CAElB;IAET;;;OAGG;IACH,qDAOC;IAOD;;;OAGG;IACH,6CAEC;IAED;;OAEG;IACH,kBAFU,qBAAqB,CAEd;IAEjB;;OAEG;IACH,kBAFU,qBAAqB,CAEd;IAEjB;;OAEG;IACH,mBAFU,sBAAsB,CAEd;IAGlB;;OAEG;IACH,gBAFU,oBAAoB,CAEf;IAEf;;OAEG;IACH,UAFU,cAAc,CAEf;IAET;;;;OAIG;IACH,kBAFU,qBAAqB,CAEd;IAEjB;;OAEG;IACH,aAFU,gBAAgB,CAEd;IAQZ;;;OAGG;IACH,uBAFU,kBAAkB,CAEN;IAEtB;;;;OAIG;IACH,yBAFU,wBAAwB,CAEV;IAExB;;;;OAIG;IACH,0BAFU,yBAAyB,CAEV;IAEzB;;;;OAIG;IACH,yBAFU,wBAAwB,CAEV;IAExB;;;;OAIG;IACH,2BAFU,0BAA0B,CAEV;IAE1B;;;OAGG;IACH,oBAFU,mBAAmB,CAEV;IAUnB;;;OAGG;IACH,8BAEC;IAED,uBAOC;IAED;;;OAGG;IACH,wBAEC;IAqCD;;;;;;;;OAQG;IACH,6DANW,sBAAsB,aACtB,oBAAoB,EAAE,cACtB;QAAC,MAAM,EAAE,YAAY,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAC,QAmE9D;IAED;;;;OAIG;IACH,gCAHW,gBAAgB,GACd,gBAAgB,CAI5B;IAED;;OAEG;IACH,+BAgBC;IAED,4BAEC;IAED,eAmDC;IAED,gBAoBC;IAGL;;;OAGG;IACH,4BAFU,OAAO,CAE0B;;CAN1C;+BAvYY,OAAO,0CAA0C,EAAE,gBAAgB;qCACnE,OAAO,kDAAkD,EAAE,sBAAsB;2BAKjF,OAAO,mCAAmC,EAAE,YAAY;mCAjBlC,kCAAkC;mCAGlC,kCAAkC;kCADnC,wBAAwB;2CAEf,mDAAmD;oCAH1D,2CAA2C;sCAbzC,6CAA6C;sCAC7C,6CAA6C;uCAF5C,8CAA8C;qCAIhD,0CAA0C;+BAgBhD,6BAA6B;sCACtB,4CAA4C;iCAfjD,+BAA+B;mCAC7B,gCAAgC;yCAC1B,sCAAsC;0CAGrC,uCAAuC;yCACxC,sCAAsC;2CAFpC,wCAAwC;oCAS/C,kCAAkC;iCAVtB,8BAA8B"}
|
|
@@ -11,6 +11,7 @@ import { GPUBufferAllocatorNative } from "./buffer/GPUBufferAllocatorNative.js";
|
|
|
11
11
|
import { create_buffer, GPUBufferContext } from "./buffer/GPUBufferContext.js";
|
|
12
12
|
import { GPUBufferReadbackAllocator } from "./buffer/GPUBufferReadbackAllocator.js";
|
|
13
13
|
import { GPUBufferStagingAllocator } from "./buffer/GPUBufferStagingAllocator.js";
|
|
14
|
+
import { GPUBufferUploadAllocator } from "./buffer/GPUBufferUploadAllocator.js";
|
|
14
15
|
import { GPUGeometryManager } from "./geometry/GPUGeometryManager.js";
|
|
15
16
|
import { GPUCollectionLimits } from "./rasterize/expand/GPUCollectionLimits.js";
|
|
16
17
|
import { GPUSamplerManager } from "./GPUSamplerManager.js";
|
|
@@ -137,11 +138,19 @@ export class GraphicsContext {
|
|
|
137
138
|
buffer_allocator_native;
|
|
138
139
|
|
|
139
140
|
/**
|
|
140
|
-
*
|
|
141
|
+
* Mapped `MAP_WRITE` buffers, one per upload: where a {@link ShadeGPUCommandContext} sends its
|
|
142
|
+
* large writes, for which a mapping is the faster road (see `MAPPED_UPLOAD_THRESHOLD`).
|
|
141
143
|
* @type {GPUBufferStagingAllocator}
|
|
142
144
|
*/
|
|
143
145
|
buffer_allocator_staging;
|
|
144
146
|
|
|
147
|
+
/**
|
|
148
|
+
* Upload blocks for {@link ShadeGPUCommandContext}'s small writes — every uniform a pass is
|
|
149
|
+
* handed by value among them. Sent with one queue write per block, not mapped.
|
|
150
|
+
* @type {GPUBufferUploadAllocator}
|
|
151
|
+
*/
|
|
152
|
+
buffer_allocator_upload;
|
|
153
|
+
|
|
145
154
|
/**
|
|
146
155
|
* Used to read data back from the GPU: `MAP_READ` buffers, held by the CPU across frames, which
|
|
147
156
|
* is why they cannot come from {@link buffer_allocator_main}.
|
|
@@ -174,8 +183,9 @@ export class GraphicsContext {
|
|
|
174
183
|
increment_time() {
|
|
175
184
|
this.#timer_increment++;
|
|
176
185
|
|
|
177
|
-
// advance the single frame clock for
|
|
186
|
+
// advance the single frame clock for the substitutable pools in lockstep
|
|
178
187
|
this.buffer_allocator_main.increment_time();
|
|
188
|
+
this.buffer_allocator_upload.increment_time();
|
|
179
189
|
this.allocator_textures.increment_time();
|
|
180
190
|
}
|
|
181
191
|
|
|
@@ -197,6 +207,7 @@ export class GraphicsContext {
|
|
|
197
207
|
this.buffer_allocator_main = new GPUBufferAllocator(device);
|
|
198
208
|
this.buffer_allocator_native = new GPUBufferAllocatorNative(device);
|
|
199
209
|
this.buffer_allocator_staging = new GPUBufferStagingAllocator(device);
|
|
210
|
+
this.buffer_allocator_upload = new GPUBufferUploadAllocator(device);
|
|
200
211
|
this.buffer_allocator_readback = new GPUBufferReadbackAllocator(device);
|
|
201
212
|
|
|
202
213
|
this.allocator_textures = new GPUTextureAllocator(device);
|
|
@@ -316,6 +327,7 @@ export class GraphicsContext {
|
|
|
316
327
|
|
|
317
328
|
r += this.buffer_allocator_main.gpu_memory_usage;
|
|
318
329
|
r += this.buffer_allocator_staging.gpu_memory_usage;
|
|
330
|
+
r += this.buffer_allocator_upload.gpu_memory_usage;
|
|
319
331
|
r += this.buffer_allocator_readback.gpu_memory_usage;
|
|
320
332
|
|
|
321
333
|
r += this.allocator_textures.gpu_memory_usage;
|
|
@@ -331,28 +343,54 @@ export class GraphicsContext {
|
|
|
331
343
|
update() {
|
|
332
344
|
const command_ctx = ShadeGPUCommandContext.create(this, 'GraphicsContext.update');
|
|
333
345
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
346
|
+
/**
|
|
347
|
+
* What the update raised, if anything. Held so the context is finished before it is
|
|
348
|
+
* re-raised: a context never finished keeps everything it took for good — an upload block,
|
|
349
|
+
* transient buffers — and a manager that throws every frame would leak that much every
|
|
350
|
+
* frame.
|
|
351
|
+
* @type {*}
|
|
352
|
+
*/
|
|
353
|
+
let update_error = null;
|
|
354
|
+
|
|
355
|
+
try {
|
|
356
|
+
// The one place per frame the meshlet pool compacts, at the head of the frame: before the
|
|
357
|
+
// clone flush in geometries.update, before the VG runtime's flush, before any pass. Its
|
|
358
|
+
// per-frame bound is a bound because this is the only call (COMPACTION_PLAN_2026_09_16
|
|
359
|
+
// §4.5).
|
|
360
|
+
this.geometries.meshlets.sweep(command_ctx);
|
|
361
|
+
|
|
362
|
+
this.geometries.update(command_ctx);
|
|
339
363
|
|
|
340
|
-
|
|
364
|
+
this.textures.update();
|
|
365
|
+
this.materials.update(command_ctx);
|
|
341
366
|
|
|
342
|
-
|
|
343
|
-
this.materials.update(command_ctx);
|
|
367
|
+
this.bind_groups.update();
|
|
344
368
|
|
|
345
|
-
|
|
369
|
+
this.increment_time();
|
|
346
370
|
|
|
347
|
-
|
|
371
|
+
this.allocator_textures.update();
|
|
348
372
|
|
|
349
|
-
|
|
373
|
+
this.#collection_limits.update(command_ctx, this.buffer_allocator_main);
|
|
374
|
+
} catch (e) {
|
|
375
|
+
update_error = e;
|
|
376
|
+
}
|
|
350
377
|
|
|
351
|
-
|
|
378
|
+
try {
|
|
379
|
+
command_ctx.finish();
|
|
380
|
+
} catch (teardown_error) {
|
|
381
|
+
if (update_error === null) {
|
|
382
|
+
throw teardown_error;
|
|
383
|
+
}
|
|
352
384
|
|
|
353
|
-
|
|
385
|
+
// already unwinding: the update's own error is the one the caller needs to see
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
if (update_error !== null) {
|
|
389
|
+
throw update_error;
|
|
390
|
+
}
|
|
354
391
|
|
|
355
392
|
this.buffer_allocator_main.update();
|
|
393
|
+
this.buffer_allocator_upload.update();
|
|
356
394
|
}
|
|
357
395
|
|
|
358
396
|
destroy() {
|
|
@@ -371,6 +409,7 @@ export class GraphicsContext {
|
|
|
371
409
|
this.buffer_allocator_main.destroy();
|
|
372
410
|
this.buffer_allocator_native.destroy();
|
|
373
411
|
this.buffer_allocator_staging.destroy();
|
|
412
|
+
this.buffer_allocator_upload.destroy();
|
|
374
413
|
this.buffer_allocator_readback.destroy();
|
|
375
414
|
|
|
376
415
|
this.#collection_limits.destroy();
|
|
@@ -210,7 +210,18 @@ export class Renderer {
|
|
|
210
210
|
* @type {Signal<ShadeDeviceFailure>}
|
|
211
211
|
*/
|
|
212
212
|
onDeviceFailure: any;
|
|
213
|
-
|
|
213
|
+
/**
|
|
214
|
+
* Sent at the end of every frame {@link render} or {@link render_to_target} completes, with the
|
|
215
|
+
* number of frames completed so far. A frame that throws is not one of them: whatever it had
|
|
216
|
+
* recorded may still have been submitted, but it sends nothing and is not counted.
|
|
217
|
+
*
|
|
218
|
+
* **Submitted, not finished.** The frame's commands have been handed to the queue and the GPU
|
|
219
|
+
* may not have started them; a listener that needs the GPU to be done with the frame waits on
|
|
220
|
+
* {@link GPUQueue#onSubmittedWorkDone} instead.
|
|
221
|
+
*
|
|
222
|
+
* @type {Signal<number>}
|
|
223
|
+
*/
|
|
224
|
+
onFrameFinished: any;
|
|
214
225
|
/**
|
|
215
226
|
*
|
|
216
227
|
* @param {number} v
|
|
@@ -440,7 +451,9 @@ export class Renderer {
|
|
|
440
451
|
* simulation, the animation tick and exposure adaptation all step by it. Zero by default, which
|
|
441
452
|
* draws the current state and moves nothing; a fixed fraction of a second here instead would run
|
|
442
453
|
* the simulation at that rate no matter what the caller's clock was doing.
|
|
443
|
-
* @returns {boolean} whether frame was
|
|
454
|
+
* @returns {boolean} whether a frame was encoded and submitted. False only when there is nothing
|
|
455
|
+
* to draw with — the device was lost, or the renderer destroyed. Frames the GPU has not finished
|
|
456
|
+
* yet neither hold this one back nor make it return false.
|
|
444
457
|
*/
|
|
445
458
|
render(camera: PerspectiveCamera, scene: Scene, time_delta_seconds?: number): boolean;
|
|
446
459
|
/**
|
|
@@ -457,11 +470,14 @@ export class Renderer {
|
|
|
457
470
|
* @param {Scene} scene
|
|
458
471
|
* @param {number} time_delta_seconds
|
|
459
472
|
* @param {GPUTextureContext} target must match {@link output_resolution}
|
|
460
|
-
* @returns {boolean} whether frame was
|
|
473
|
+
* @returns {boolean} whether a frame was encoded and submitted. False only when there is nothing
|
|
474
|
+
* to draw with — the device was lost, or the renderer destroyed. Frames the GPU has not finished
|
|
475
|
+
* yet neither hold this one back nor make it return false.
|
|
461
476
|
*/
|
|
462
477
|
render_to_target(camera: PerspectiveCamera, scene: Scene, time_delta_seconds: number, target: GPUTextureContext): boolean;
|
|
463
478
|
#private;
|
|
464
479
|
}
|
|
480
|
+
export type GPUFrameRecorder = import("../device/timing/profile/GPUFrameRecorder.js").GPUFrameRecorder;
|
|
465
481
|
export type GPUProfileSession = import("../device/timing/profile/GPUProfileSession.js").GPUProfileSession;
|
|
466
482
|
export type PerspectiveCamera = import("./camera/PerspectiveCamera.js").PerspectiveCamera;
|
|
467
483
|
export type RenderExtension = import("./extension/RenderExtension.js").RenderExtension;
|
|
@@ -477,7 +493,6 @@ import { DepthOfField } from "./postprocess/dof/raymarch/DepthOfField.js";
|
|
|
477
493
|
import { DepthOfFieldU } from "./postprocess/dof/gather/DepthOfFieldU.js";
|
|
478
494
|
import { ViewManager } from "./view/ViewManager.js";
|
|
479
495
|
import { GraphicsContext } from "./GraphicsContext.js";
|
|
480
|
-
import Signal from "../../core/events/signal/Signal.js";
|
|
481
496
|
import Vector2 from "../../core/geom/Vector2.js";
|
|
482
497
|
import { GPUTextureContext } from "./texture/GPUTextureContext.js";
|
|
483
498
|
import { FramePhase } from "./extension/FramePhase.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Renderer.d.ts","sourceRoot":"","sources":["../../../../src/shade/renderer/Renderer.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Renderer.d.ts","sourceRoot":"","sources":["../../../../src/shade/renderer/Renderer.js"],"names":[],"mappings":"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"}
|