@woosh/meep-engine 3.32.0 → 3.33.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.
Files changed (58) hide show
  1. package/build/bundle-worker-terrain.js +1 -1
  2. package/package.json +1 -1
  3. package/src/core/collection/table/RowFirstTable.d.ts +8 -0
  4. package/src/core/collection/table/RowFirstTable.d.ts.map +1 -1
  5. package/src/core/collection/table/RowFirstTable.js +40 -11
  6. package/src/engine/graphics/ecs/sprite/Sprite.d.ts +3 -0
  7. package/src/engine/graphics/ecs/sprite/Sprite.d.ts.map +1 -1
  8. package/src/engine/graphics/ecs/sprite/Sprite.js +3 -0
  9. package/src/engine/graphics/ecs/sprite/SpriteSystemPE.d.ts +3 -0
  10. package/src/engine/graphics/ecs/sprite/SpriteSystemPE.d.ts.map +1 -1
  11. package/src/engine/graphics/ecs/sprite/SpriteSystemPE.js +3 -0
  12. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  13. package/src/shade/device/mock/SoftwareGPURenderPassEncoder.d.ts +20 -3
  14. package/src/shade/device/mock/SoftwareGPURenderPassEncoder.d.ts.map +1 -1
  15. package/src/shade/device/mock/SoftwareGPURenderPassEncoder.js +21 -3
  16. package/src/shade/renderer/GraphicsContext.d.ts +11 -0
  17. package/src/shade/renderer/GraphicsContext.d.ts.map +1 -1
  18. package/src/shade/renderer/GraphicsContext.js +52 -38
  19. package/src/shade/renderer/buffer/GPUBufferReadbackAllocator.d.ts +6 -5
  20. package/src/shade/renderer/buffer/GPUBufferReadbackAllocator.d.ts.map +1 -1
  21. package/src/shade/renderer/buffer/GPUBufferReadbackAllocator.js +241 -240
  22. package/src/shade/renderer/buffer/GPUBufferStagingAllocator.d.ts +51 -0
  23. package/src/shade/renderer/buffer/GPUBufferStagingAllocator.d.ts.map +1 -1
  24. package/src/shade/renderer/buffer/GPUBufferStagingAllocator.js +214 -28
  25. package/src/shade/renderer/dynamic/DynamicMeshAVBOITChannel.d.ts +2 -1
  26. package/src/shade/renderer/dynamic/DynamicMeshAVBOITChannel.d.ts.map +1 -1
  27. package/src/shade/renderer/dynamic/DynamicMeshAVBOITChannel.js +19 -17
  28. package/src/shade/renderer/dynamic/GPUDynamicMeshDrawList.d.ts +70 -0
  29. package/src/shade/renderer/dynamic/GPUDynamicMeshDrawList.d.ts.map +1 -0
  30. package/src/shade/renderer/dynamic/GPUDynamicMeshDrawList.js +257 -0
  31. package/src/shade/renderer/dynamic/GPUDynamicMeshRenderer.d.ts.map +1 -1
  32. package/src/shade/renderer/dynamic/GPUDynamicMeshRenderer.js +19 -34
  33. package/src/shade/renderer/dynamic/GPUDynamicMeshResidency.d.ts +6 -20
  34. package/src/shade/renderer/dynamic/GPUDynamicMeshResidency.d.ts.map +1 -1
  35. package/src/shade/renderer/dynamic/GPUDynamicMeshResidency.js +42 -36
  36. package/src/shade/renderer/dynamic/chunk_dynamic_mesh_avboit_vertex.d.ts +2 -1
  37. package/src/shade/renderer/dynamic/chunk_dynamic_mesh_avboit_vertex.d.ts.map +1 -1
  38. package/src/shade/renderer/dynamic/chunk_dynamic_mesh_avboit_vertex.js +4 -3
  39. package/src/shade/renderer/dynamic/chunk_dynamic_mesh_vertex.d.ts +4 -3
  40. package/src/shade/renderer/dynamic/chunk_dynamic_mesh_vertex.d.ts.map +1 -1
  41. package/src/shade/renderer/dynamic/chunk_dynamic_mesh_vertex.js +7 -4
  42. package/src/shade/renderer/dynamic/graph_dynamic_mesh_avboit.d.ts +14 -15
  43. package/src/shade/renderer/dynamic/graph_dynamic_mesh_avboit.d.ts.map +1 -1
  44. package/src/shade/renderer/dynamic/graph_dynamic_mesh_avboit.js +49 -83
  45. package/src/shade/renderer/dynamic/shader_dynamic_mesh.d.ts +19 -3
  46. package/src/shade/renderer/dynamic/shader_dynamic_mesh.d.ts.map +1 -1
  47. package/src/shade/renderer/dynamic/shader_dynamic_mesh.js +26 -6
  48. package/src/shade/renderer/dynamic/shader_dynamic_mesh_avboit_draw.d.ts +2 -1
  49. package/src/shade/renderer/dynamic/shader_dynamic_mesh_avboit_draw.d.ts.map +1 -1
  50. package/src/shade/renderer/dynamic/shader_dynamic_mesh_avboit_draw.js +12 -6
  51. package/src/shade/renderer/dynamic/shader_dynamic_mesh_avboit_splat.d.ts +3 -2
  52. package/src/shade/renderer/dynamic/shader_dynamic_mesh_avboit_splat.d.ts.map +1 -1
  53. package/src/shade/renderer/dynamic/shader_dynamic_mesh_avboit_splat.js +21 -13
  54. package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +1 -1
  55. package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
  56. package/src/shade/renderer/rasterize/native/avboit/AVBOIT_LEDGER.md +20 -0
  57. package/src/shade/renderer/shader/type/serde/write_gpu_typed_buffer.d.ts.map +1 -1
  58. package/src/shade/renderer/shader/type/serde/write_gpu_typed_buffer.js +8 -1
@@ -1,10 +1,10 @@
1
1
  /**
2
- * Upload the live meshes, then mark the depth slices their world boxes span
2
+ * Upload the live meshes and write their draws, then mark the depth slices their world boxes span
3
3
  * (`shader_dynamic_mesh_avboit_occupancy`).
4
4
  *
5
- * **This is the pass that brings the vertices up to date**, being the channel's first: the device is
6
- * only reachable at execution time, and the splat and the draw that read the buffers run later in the
7
- * same frame, behind the warp this pass's output feeds.
5
+ * **This is the pass that brings the vertices and the draws' constants up to date**, being the
6
+ * channel's first: the device is only reachable at execution time, and the splat and the draw that
7
+ * read them run later in the same frame, behind the warp this pass's output feeds.
8
8
  *
9
9
  * @param {object} params
10
10
  * @param {import("../../../engine/graphics/render/frame_graph/FrameGraph.js").FrameGraph} params.graph
@@ -14,9 +14,11 @@
14
14
  * @param {GPUDynamicMeshResidencyTable} params.residency
15
15
  * @param {DynamicMesh[]} params.meshes the live meshes, one box each
16
16
  * @param {Float32Array} params.boxes world boxes, {@link DYNAMIC_MESH_AVBOIT_BOX_FLOATS} floats per mesh
17
+ * @param {GPUDynamicMeshDrawList} params.draws the frame's draws, written here for the splat and the
18
+ * draw of the same frame
17
19
  * @returns {number} the occupancy handle after the write
18
20
  */
19
- export function graph_dynamic_mesh_avboit_occupancy({ graph, camera, cluster_parameters, occupancy, residency, meshes, boxes, }: {
21
+ export function graph_dynamic_mesh_avboit_occupancy({ graph, camera, cluster_parameters, occupancy, residency, meshes, boxes, draws, }: {
20
22
  graph: import("../../../engine/graphics/render/frame_graph/FrameGraph.js").FrameGraph;
21
23
  camera: number;
22
24
  cluster_parameters: ArrayLike<number>;
@@ -24,6 +26,7 @@ export function graph_dynamic_mesh_avboit_occupancy({ graph, camera, cluster_par
24
26
  residency: GPUDynamicMeshResidencyTable;
25
27
  meshes: DynamicMesh[];
26
28
  boxes: Float32Array;
29
+ draws: GPUDynamicMeshDrawList;
27
30
  }): number;
28
31
  /**
29
32
  * Splat the live meshes' extinction into the voxel volume (`shader_dynamic_mesh_avboit_splat`).
@@ -38,11 +41,10 @@ export function graph_dynamic_mesh_avboit_occupancy({ graph, camera, cluster_par
38
41
  * @param {number} params.warp graph handle
39
42
  * @param {number[]} params.voxel_resolution the volume's width and height, which the raster is
40
43
  * @param {{extinction: number, overflow: number, dummy: number}} params.volume the volume, to add to
41
- * @param {GPUDynamicMeshResidencyTable} params.residency
42
- * @param {DynamicMesh[]} params.meshes the live meshes
44
+ * @param {GPUDynamicMeshDrawList} params.draws the frame's draws, as the occupancy wrote them
43
45
  * @returns {{extinction: number, overflow: number, dummy: number}} the volume after the write
44
46
  */
45
- export function graph_dynamic_mesh_avboit_splat({ graph, camera, warp, voxel_resolution, volume, residency, meshes, }: {
47
+ export function graph_dynamic_mesh_avboit_splat({ graph, camera, warp, voxel_resolution, volume, draws, }: {
46
48
  graph: import("../../../engine/graphics/render/frame_graph/FrameGraph.js").FrameGraph;
47
49
  camera: number;
48
50
  warp: number;
@@ -52,8 +54,7 @@ export function graph_dynamic_mesh_avboit_splat({ graph, camera, warp, voxel_res
52
54
  overflow: number;
53
55
  dummy: number;
54
56
  };
55
- residency: GPUDynamicMeshResidencyTable;
56
- meshes: DynamicMesh[];
57
+ draws: GPUDynamicMeshDrawList;
57
58
  }): {
58
59
  extinction: number;
59
60
  overflow: number;
@@ -72,11 +73,10 @@ export function graph_dynamic_mesh_avboit_splat({ graph, camera, warp, voxel_res
72
73
  * @param {number} params.volumetrics_lut graph handle
73
74
  * @param {number} params.volumetrics_metadata graph handle
74
75
  * @param {{color: number, norm: number, extinction: number, emission: number}} params.accumulators to add to
75
- * @param {GPUDynamicMeshResidencyTable} params.residency
76
- * @param {DynamicMesh[]} params.meshes the live meshes
76
+ * @param {GPUDynamicMeshDrawList} params.draws the frame's draws, as the occupancy wrote them
77
77
  * @returns {{color: number, norm: number, extinction: number, emission: number}} the accumulators after the draw
78
78
  */
79
- export function graph_dynamic_mesh_avboit_draw({ graph, view_ctx, camera, depth_texture, warp, integral, volumetrics_lut, volumetrics_metadata, accumulators, residency, meshes, }: {
79
+ export function graph_dynamic_mesh_avboit_draw({ graph, view_ctx, camera, depth_texture, warp, integral, volumetrics_lut, volumetrics_metadata, accumulators, draws, }: {
80
80
  graph: import("../../../engine/graphics/render/frame_graph/FrameGraph.js").FrameGraph;
81
81
  view_ctx: import("../view/GPUViewContext.js").GPUViewContext;
82
82
  camera: number;
@@ -91,8 +91,7 @@ export function graph_dynamic_mesh_avboit_draw({ graph, view_ctx, camera, depth_
91
91
  extinction: number;
92
92
  emission: number;
93
93
  };
94
- residency: GPUDynamicMeshResidencyTable;
95
- meshes: DynamicMesh[];
94
+ draws: GPUDynamicMeshDrawList;
96
95
  }): {
97
96
  color: number;
98
97
  norm: number;
@@ -1 +1 @@
1
- {"version":3,"file":"graph_dynamic_mesh_avboit.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/dynamic/graph_dynamic_mesh_avboit.js"],"names":[],"mappings":"AA2EA;;;;;;;;;;;;;;;;;GAiBG;AACH;IATkG,KAAK,EAA5F,OAAO,2DAA2D,EAAE,UAAU;IAC/D,MAAM,EAArB,MAAM;IACoB,kBAAkB,EAA5C,UAAU,MAAM,CAAC;IACF,SAAS,EAAxB,MAAM;IAC+B,SAAS;IACxB,MAAM,EAA5B,aAAa;IACQ,KAAK,EAA1B,YAAY;IACV,MAAM,CAqDlB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH;IATkG,KAAK,EAA5F,OAAO,2DAA2D,EAAE,UAAU;IAC/D,MAAM,EAArB,MAAM;IACS,IAAI,EAAnB,MAAM;IACW,gBAAgB,EAAjC,MAAM,EAAE;IACsD,MAAM,EAApE;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAC;IAChB,SAAS;IACxB,MAAM,EAA5B,aAAa;IACX;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAC,CA0FjE;AAED;;;;;;;;;;;;;;;;GAgBG;AACH;IAbkG,KAAK,EAA5F,OAAO,2DAA2D,EAAE,UAAU;IACnB,QAAQ,EAAnE,OAAO,2BAA2B,EAAE,cAAc;IACnC,MAAM,EAArB,MAAM;IACS,aAAa,EAA5B,MAAM;IACS,IAAI,EAAnB,MAAM;IACS,QAAQ,EAAvB,MAAM;IACS,eAAe,EAA9B,MAAM;IACS,oBAAoB,EAAnC,MAAM;IACsE,YAAY,EAAxF;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAC;IAC9B,SAAS;IACxB,MAAM,EAA5B,aAAa;IACX;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAC,CA+F/E"}
1
+ {"version":3,"file":"graph_dynamic_mesh_avboit.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/dynamic/graph_dynamic_mesh_avboit.js"],"names":[],"mappings":"AA4CA;;;;;;;;;;;;;;;;;;;GAmBG;AACH;IAXkG,KAAK,EAA5F,OAAO,2DAA2D,EAAE,UAAU;IAC/D,MAAM,EAArB,MAAM;IACoB,kBAAkB,EAA5C,UAAU,MAAM,CAAC;IACF,SAAS,EAAxB,MAAM;IAC+B,SAAS;IACxB,MAAM,EAA5B,aAAa;IACQ,KAAK,EAA1B,YAAY;IACmB,KAAK;IAElC,MAAM,CAwDlB;AAED;;;;;;;;;;;;;;;GAeG;AACH;IARkG,KAAK,EAA5F,OAAO,2DAA2D,EAAE,UAAU;IAC/D,MAAM,EAArB,MAAM;IACS,IAAI,EAAnB,MAAM;IACW,gBAAgB,EAAjC,MAAM,EAAE;IACsD,MAAM,EAApE;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAC;IACtB,KAAK;IAClC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAC,CAuFjE;AAED;;;;;;;;;;;;;;;GAeG;AACH;IAZkG,KAAK,EAA5F,OAAO,2DAA2D,EAAE,UAAU;IACnB,QAAQ,EAAnE,OAAO,2BAA2B,EAAE,cAAc;IACnC,MAAM,EAArB,MAAM;IACS,aAAa,EAA5B,MAAM;IACS,IAAI,EAAnB,MAAM;IACS,QAAQ,EAAvB,MAAM;IACS,eAAe,EAA9B,MAAM;IACS,oBAAoB,EAAnC,MAAM;IACsE,YAAY,EAAxF;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAC;IACpC,KAAK;IAClC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAC,CA4F/E"}
@@ -28,58 +28,27 @@ import {
28
28
  /**
29
29
  * The dynamic meshes' three contributions to the AVBOIT transparency pipeline — the
30
30
  * `AVBOITSideChannel` contract, recorded into the frame graph the way the AVBOIT orchestrator records
31
- * its own passes. `DynamicMeshAVBOITChannel` calls these with the meshes it found live this frame and
32
- * the handles the orchestrator hands it.
31
+ * its own passes. `DynamicMeshAVBOITChannel` calls these with what it decided for the frame — the
32
+ * occupancy with the meshes it found live, the splat and the draw with the list the occupancy writes
33
+ * their draws into — and the handles the orchestrator hands it.
33
34
  *
34
- * One draw per mesh in the splat and in the draw, as in the pass over the scene: each mesh has its
35
- * own vertex and index buffers, so its own group 0. Order does not matter to any of them — the volume
36
- * and the accumulators are sums — which is why nothing here sorts.
35
+ * One draw per mesh in the splat and in the draw, as in the pass over the scene, out of one
36
+ * {@link GPUDynamicMeshDrawList} per frame: the occupancy writes it, the splat and the draw both draw
37
+ * it, so the meshes' constants go up once a frame and the two passes read the same ones. Order does
38
+ * not matter to any of them — the volume and the accumulators are sums — which is why nothing here
39
+ * sorts.
37
40
  */
38
41
 
39
42
  /** The accumulators' and the splat target's view: one mip, the one the frame draws into. */
40
43
  const COLOR_VIEW = TextureViewDescriptor.from({ mipLevelCount: 1, baseMipLevel: 0 });
41
44
 
42
45
  /**
43
- * Every live mesh's bindings for one pass: its own group 0, as its residency builds it for the pass
44
- * over the scene, then the pass's groups, the same for every draw.
45
- *
46
- * **Before the render pass is opened**: staging a mesh's draw uniform records a copy onto the
47
- * command encoder, and the encoder is locked for as long as a pass is open on it.
48
- *
49
- * @param {ShadeGPUCommandContext} encoder
50
- * @param {GPUDynamicMeshResidencyTable} residency
51
- * @param {DynamicMesh[]} meshes
52
- * @param {GPUBuffer} camera
53
- * @param {GPUBindingResource[][]} pass_groups groups 1 and up
54
- * @returns {{residency: GPUDynamicMeshResidency, bindings: GPUBindingResource[][]}[]}
55
- */
56
- function prepare_draws(encoder, residency, meshes, camera, pass_groups) {
57
- const draws = [];
58
-
59
- for (let i = 0; i < meshes.length; i++) {
60
- const mesh = meshes[i];
61
- const resident = residency.get(mesh.geometry);
62
-
63
- if (resident === undefined || resident.index_count === 0) {
64
- // not uploaded by this frame's occupancy pass, or nothing to draw
65
- continue;
66
- }
67
-
68
- const [mesh_group] = resident.create_bindings(encoder, mesh, camera);
69
-
70
- draws.push({ residency: resident, bindings: [mesh_group, ...pass_groups] });
71
- }
72
-
73
- return draws;
74
- }
75
-
76
- /**
77
- * Upload the live meshes, then mark the depth slices their world boxes span
46
+ * Upload the live meshes and write their draws, then mark the depth slices their world boxes span
78
47
  * (`shader_dynamic_mesh_avboit_occupancy`).
79
48
  *
80
- * **This is the pass that brings the vertices up to date**, being the channel's first: the device is
81
- * only reachable at execution time, and the splat and the draw that read the buffers run later in the
82
- * same frame, behind the warp this pass's output feeds.
49
+ * **This is the pass that brings the vertices and the draws' constants up to date**, being the
50
+ * channel's first: the device is only reachable at execution time, and the splat and the draw that
51
+ * read them run later in the same frame, behind the warp this pass's output feeds.
83
52
  *
84
53
  * @param {object} params
85
54
  * @param {import("../../../engine/graphics/render/frame_graph/FrameGraph.js").FrameGraph} params.graph
@@ -89,6 +58,8 @@ function prepare_draws(encoder, residency, meshes, camera, pass_groups) {
89
58
  * @param {GPUDynamicMeshResidencyTable} params.residency
90
59
  * @param {DynamicMesh[]} params.meshes the live meshes, one box each
91
60
  * @param {Float32Array} params.boxes world boxes, {@link DYNAMIC_MESH_AVBOIT_BOX_FLOATS} floats per mesh
61
+ * @param {GPUDynamicMeshDrawList} params.draws the frame's draws, written here for the splat and the
62
+ * draw of the same frame
92
63
  * @returns {number} the occupancy handle after the write
93
64
  */
94
65
  export function graph_dynamic_mesh_avboit_occupancy({
@@ -99,6 +70,7 @@ export function graph_dynamic_mesh_avboit_occupancy({
99
70
  residency,
100
71
  meshes,
101
72
  boxes,
73
+ draws,
102
74
  }) {
103
75
  assert.isNonNegativeInteger(camera, "camera");
104
76
  assert.isNonNegativeInteger(occupancy, "occupancy");
@@ -115,6 +87,8 @@ export function graph_dynamic_mesh_avboit_occupancy({
115
87
 
116
88
  residency.upload(context.graphics.device, meshes);
117
89
 
90
+ draws.write(encoder, residency, meshes);
91
+
118
92
  shader_dynamic_mesh_avboit_occupancy.dispatch({
119
93
  encoder,
120
94
  bindings: {
@@ -157,8 +131,7 @@ export function graph_dynamic_mesh_avboit_occupancy({
157
131
  * @param {number} params.warp graph handle
158
132
  * @param {number[]} params.voxel_resolution the volume's width and height, which the raster is
159
133
  * @param {{extinction: number, overflow: number, dummy: number}} params.volume the volume, to add to
160
- * @param {GPUDynamicMeshResidencyTable} params.residency
161
- * @param {DynamicMesh[]} params.meshes the live meshes
134
+ * @param {GPUDynamicMeshDrawList} params.draws the frame's draws, as the occupancy wrote them
162
135
  * @returns {{extinction: number, overflow: number, dummy: number}} the volume after the write
163
136
  */
164
137
  export function graph_dynamic_mesh_avboit_splat({
@@ -167,8 +140,7 @@ export function graph_dynamic_mesh_avboit_splat({
167
140
  warp,
168
141
  voxel_resolution,
169
142
  volume,
170
- residency,
171
- meshes,
143
+ draws,
172
144
  }) {
173
145
  assert.isNonNegativeInteger(camera, "camera");
174
146
  assert.isNonNegativeInteger(warp, "warp");
@@ -179,31 +151,30 @@ export function graph_dynamic_mesh_avboit_splat({
179
151
  const encoder = context.encoder;
180
152
  const graphics = context.graphics;
181
153
 
154
+ if (draws.count === 0) {
155
+ return;
156
+ }
157
+
158
+ const pipeline = DYNAMIC_MESH_AVBOIT_SPLAT_PIPELINE;
159
+
182
160
  // By name, never by position (ledger entry 21): the order a shader declares its bindings in
183
161
  // is the shader's business.
184
162
  const groups = DYNAMIC_MESH_AVBOIT_SPLAT_RESOURCES.groups;
185
163
 
186
- const pass_groups = [
187
- groups[DYNAMIC_MESH_AVBOIT_SPLAT_BIND_GROUP_PASS].generateBindings({
188
- warp: resources.get(data.warp),
189
- }, encoder),
190
- groups[DYNAMIC_MESH_AVBOIT_SPLAT_BIND_GROUP_VOLUME].generateBindings({
191
- extinction_volume: resources.get(data.extinction),
192
- overflow_slice: resources.get(data.overflow),
193
- }, encoder),
194
- ];
195
-
196
- const draws = prepare_draws(encoder, residency, meshes, resources.get(data.camera), pass_groups);
164
+ const pass_group = groups[DYNAMIC_MESH_AVBOIT_SPLAT_BIND_GROUP_PASS].generateBindings({
165
+ warp: resources.get(data.warp),
166
+ }, encoder);
197
167
 
198
- if (draws.length === 0) {
199
- return;
200
- }
168
+ const volume_group = groups[DYNAMIC_MESH_AVBOIT_SPLAT_BIND_GROUP_VOLUME].generateBindings({
169
+ extinction_volume: resources.get(data.extinction),
170
+ overflow_slice: resources.get(data.overflow),
171
+ }, encoder);
201
172
 
202
173
  // the target is never written; it only sizes the raster and gives it its samples
203
174
  const pass_encoder = encoder.constructRenderPass({
204
175
  label: "Dynamic Mesh AVBOIT Splat",
205
- pipeline: DYNAMIC_MESH_AVBOIT_SPLAT_PIPELINE,
206
- // group 0 differs per mesh, so every group is set per draw
176
+ pipeline,
177
+ // the pass's groups are set once, just below; the draws set their own
207
178
  bindings: [],
208
179
  colorAttachments: [{
209
180
  view: resources.get(data.target).obtainView(COLOR_VIEW),
@@ -212,11 +183,10 @@ export function graph_dynamic_mesh_avboit_splat({
212
183
  }],
213
184
  });
214
185
 
215
- for (let i = 0; i < draws.length; i++) {
216
- const draw = draws[i];
186
+ graphics.setPipelineBindGroup(pass_encoder, pipeline, DYNAMIC_MESH_AVBOIT_SPLAT_BIND_GROUP_PASS, pass_group);
187
+ graphics.setPipelineBindGroup(pass_encoder, pipeline, DYNAMIC_MESH_AVBOIT_SPLAT_BIND_GROUP_VOLUME, volume_group);
217
188
 
218
- draw.residency.draw(pass_encoder, graphics, DYNAMIC_MESH_AVBOIT_SPLAT_PIPELINE, draw.bindings);
219
- }
189
+ draws.draw(pass_encoder, graphics, pipeline, resources.get(data.camera));
220
190
 
221
191
  pass_encoder.end();
222
192
  }
@@ -264,8 +234,7 @@ export function graph_dynamic_mesh_avboit_splat({
264
234
  * @param {number} params.volumetrics_lut graph handle
265
235
  * @param {number} params.volumetrics_metadata graph handle
266
236
  * @param {{color: number, norm: number, extinction: number, emission: number}} params.accumulators to add to
267
- * @param {GPUDynamicMeshResidencyTable} params.residency
268
- * @param {DynamicMesh[]} params.meshes the live meshes
237
+ * @param {GPUDynamicMeshDrawList} params.draws the frame's draws, as the occupancy wrote them
269
238
  * @returns {{color: number, norm: number, extinction: number, emission: number}} the accumulators after the draw
270
239
  */
271
240
  export function graph_dynamic_mesh_avboit_draw({
@@ -278,8 +247,7 @@ export function graph_dynamic_mesh_avboit_draw({
278
247
  volumetrics_lut,
279
248
  volumetrics_metadata,
280
249
  accumulators,
281
- residency,
282
- meshes,
250
+ draws,
283
251
  }) {
284
252
  assert.isNonNegativeInteger(camera, "camera");
285
253
  assert.isNonNegativeInteger(depth_texture, "depth_texture");
@@ -291,6 +259,12 @@ export function graph_dynamic_mesh_avboit_draw({
291
259
  const encoder = context.encoder;
292
260
  const graphics = context.graphics;
293
261
 
262
+ if (draws.count === 0) {
263
+ return;
264
+ }
265
+
266
+ const pipeline = DYNAMIC_MESH_AVBOIT_DRAW_PIPELINE;
267
+
294
268
  // by name rather than by position, for the reason the splat gives
295
269
  const pass_group = DYNAMIC_MESH_AVBOIT_DRAW_RESOURCES.groups[DYNAMIC_MESH_AVBOIT_DRAW_BIND_GROUP_PASS].generateBindings({
296
270
  view: view_ctx.uniform_buffer.buffer,
@@ -302,12 +276,6 @@ export function graph_dynamic_mesh_avboit_draw({
302
276
  tSTBN_vec3: graphics.textures.obtain(STATIC_GRAPHICS_ENGINE_ASSETS.stbn_vec3).obtainView(),
303
277
  }, encoder);
304
278
 
305
- const draws = prepare_draws(encoder, residency, meshes, resources.get(data.camera), [pass_group]);
306
-
307
- if (draws.length === 0) {
308
- return;
309
- }
310
-
311
279
  const attachment = (handle) => ({
312
280
  view: resources.get(handle).obtainView(COLOR_VIEW),
313
281
  loadOp: "load",
@@ -316,8 +284,8 @@ export function graph_dynamic_mesh_avboit_draw({
316
284
 
317
285
  const pass_encoder = encoder.constructRenderPass({
318
286
  label: "Dynamic Mesh AVBOIT Draw",
319
- pipeline: DYNAMIC_MESH_AVBOIT_DRAW_PIPELINE,
320
- // group 0 differs per mesh, so every group is set per draw
287
+ pipeline,
288
+ // the pass's group is set once, just below; the draws set their own
321
289
  bindings: [],
322
290
  colorAttachments: [
323
291
  attachment(data.color),
@@ -331,11 +299,9 @@ export function graph_dynamic_mesh_avboit_draw({
331
299
  },
332
300
  });
333
301
 
334
- for (let i = 0; i < draws.length; i++) {
335
- const draw = draws[i];
302
+ graphics.setPipelineBindGroup(pass_encoder, pipeline, DYNAMIC_MESH_AVBOIT_DRAW_BIND_GROUP_PASS, pass_group);
336
303
 
337
- draw.residency.draw(pass_encoder, graphics, DYNAMIC_MESH_AVBOIT_DRAW_PIPELINE, draw.bindings);
338
- }
304
+ draws.draw(pass_encoder, graphics, pipeline, resources.get(data.camera));
339
305
 
340
306
  pass_encoder.end();
341
307
  }
@@ -28,12 +28,28 @@ export function create_dynamic_mesh_pipeline({ color_format, depth_format, depth
28
28
  opaque?: boolean;
29
29
  }): RenderPipelineDescriptor;
30
30
  /**
31
- * Per-draw constants. One dynamic mesh is one draw, so this is small and rewritten per mesh per
32
- * frame rather than tabled.
31
+ * Per-draw constants: one row of a frame's table of them, which a draw finds at its
32
+ * `instance_index` — its `first_instance`, since each draw is one instance.
33
+ *
34
+ * Every row is written anew every frame. A dynamic mesh's transform and colour are its to change as
35
+ * often as its vertices, so nothing about them is assumed to carry over from one frame to the next.
33
36
  */
34
37
  export const DYNAMIC_MESH_DRAW_STRUCT: WebGPUStruct;
35
38
  /**
36
- * The pipeline's resource set, for building bind groups.
39
+ * Bind group of the camera and one chunk of the frame's draw constants (`draws`), set once per chunk.
40
+ * @type {number}
41
+ */
42
+ export const DYNAMIC_MESH_BIND_GROUP_DRAWS: number;
43
+ /**
44
+ * Bind group of one geometry's `vertices` and `indices`, set per draw. The same group from frame to
45
+ * frame, for as long as the geometry's buffers keep their size.
46
+ * @type {number}
47
+ */
48
+ export const DYNAMIC_MESH_BIND_GROUP_GEOMETRY: number;
49
+ /**
50
+ * The pipeline's resource set, for building bind groups: {@link DYNAMIC_MESH_BIND_GROUP_DRAWS} and
51
+ * {@link DYNAMIC_MESH_BIND_GROUP_GEOMETRY}, which every pipeline that draws a dynamic mesh opens its
52
+ * layout with.
37
53
  *
38
54
  * @type {ShaderResourceSetDescriptor}
39
55
  */
@@ -1 +1 @@
1
- {"version":3,"file":"shader_dynamic_mesh.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/dynamic/shader_dynamic_mesh.js"],"names":[],"mappings":"AA4FA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH;IAN4B,YAAY,GAA7B,MAAM;IACW,YAAY,GAA7B,MAAM;IACuB,aAAa;IACxB,MAAM,GAAxB,OAAO;IACL,wBAAwB,CAgCpC;AArID;;;GAGG;AACH,oDAY6B;AAuH7B;;;;GAIG;AACH,qCAFU,2BAA2B,CAEW;yCAtJP,8DAA8D;6BAO1E,gCAAgC;4CAJjB,mDAAmD"}
1
+ {"version":3,"file":"shader_dynamic_mesh.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/dynamic/shader_dynamic_mesh.js"],"names":[],"mappings":"AA8GA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH;IAN4B,YAAY,GAA7B,MAAM;IACW,YAAY,GAA7B,MAAM;IACuB,aAAa;IACxB,MAAM,GAAxB,OAAO;IACL,wBAAwB,CAgCpC;AAvJD;;;;;;GAMG;AACH,oDAY6B;AAE7B;;;GAGG;AACH,4CAFU,MAAM,CAE+B;AAE/C;;;;GAIG;AACH,+CAFU,MAAM,CAEkC;AAyHlD;;;;;;GAMG;AACH,qCAFU,2BAA2B,CAEW;yCA1KP,8DAA8D;6BAO1E,gCAAgC;4CAJjB,mDAAmD"}
@@ -11,8 +11,11 @@ import { WebGPUStruct } from "../shader/type/WebGPUStruct.js";
11
11
  import { chunk_dynamic_mesh_vertex } from "./chunk_dynamic_mesh_vertex.js";
12
12
 
13
13
  /**
14
- * Per-draw constants. One dynamic mesh is one draw, so this is small and rewritten per mesh per
15
- * frame rather than tabled.
14
+ * Per-draw constants: one row of a frame's table of them, which a draw finds at its
15
+ * `instance_index` — its `first_instance`, since each draw is one instance.
16
+ *
17
+ * Every row is written anew every frame. A dynamic mesh's transform and colour are its to change as
18
+ * often as its vertices, so nothing about them is assumed to carry over from one frame to the next.
16
19
  */
17
20
  export const DYNAMIC_MESH_DRAW_STRUCT = WebGPUStruct.from({
18
21
  /**
@@ -28,11 +31,26 @@ export const DYNAMIC_MESH_DRAW_STRUCT = WebGPUStruct.from({
28
31
  color: vec4f,
29
32
  }, "DynamicMeshDraw").pack();
30
33
 
34
+ /**
35
+ * Bind group of the camera and one chunk of the frame's draw constants (`draws`), set once per chunk.
36
+ * @type {number}
37
+ */
38
+ export const DYNAMIC_MESH_BIND_GROUP_DRAWS = 0;
39
+
40
+ /**
41
+ * Bind group of one geometry's `vertices` and `indices`, set per draw. The same group from frame to
42
+ * frame, for as long as the geometry's buffers keep their size.
43
+ * @type {number}
44
+ */
45
+ export const DYNAMIC_MESH_BIND_GROUP_GEOMETRY = 1;
46
+
31
47
  const resources = new ShaderResourceSetDescriptor();
32
48
 
33
49
  resources.createGroup()
34
50
  .addUniform("camera", CAMERA_UNIFORM_STRUCT)
35
- .addUniform("draw", DYNAMIC_MESH_DRAW_STRUCT)
51
+ .addStorageBuffer("draws", WebGPUArray.from(DYNAMIC_MESH_DRAW_STRUCT), false);
52
+
53
+ resources.createGroup()
36
54
  .addStorageBuffer("vertices", WebGPUArray.f32, false)
37
55
  .addStorageBuffer("indices", WebGPUArray.u32, false);
38
56
 
@@ -45,8 +63,8 @@ struct DynamicMeshVertexOut {
45
63
  }
46
64
 
47
65
  @vertex
48
- fn vs_main(@builtin(vertex_index) vi : u32) -> DynamicMeshVertexOut {
49
- let vertex = dynamic_mesh_vertex(vi);
66
+ fn vs_main(@builtin(vertex_index) vi : u32, @builtin(instance_index) draw_index : u32) -> DynamicMeshVertexOut {
67
+ let vertex = dynamic_mesh_vertex(vi, draw_index);
50
68
 
51
69
  var out : DynamicMeshVertexOut;
52
70
 
@@ -146,7 +164,9 @@ export function create_dynamic_mesh_pipeline({
146
164
  }
147
165
 
148
166
  /**
149
- * The pipeline's resource set, for building bind groups.
167
+ * The pipeline's resource set, for building bind groups: {@link DYNAMIC_MESH_BIND_GROUP_DRAWS} and
168
+ * {@link DYNAMIC_MESH_BIND_GROUP_GEOMETRY}, which every pipeline that draws a dynamic mesh opens its
169
+ * layout with.
150
170
  *
151
171
  * @type {ShaderResourceSetDescriptor}
152
172
  */
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * Bind group of everything the draw reads once per pass — the view, the warp, the integral and the
3
- * fog. Group 0 is the dynamic-mesh group, per mesh.
3
+ * fog. Groups 0 and 1 are the dynamic-mesh groups: the draw constants per chunk, the geometry per
4
+ * mesh.
4
5
  * @type {number}
5
6
  */
6
7
  export const DYNAMIC_MESH_AVBOIT_DRAW_BIND_GROUP_PASS: number;
@@ -1 +1 @@
1
- {"version":3,"file":"shader_dynamic_mesh_avboit_draw.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/dynamic/shader_dynamic_mesh_avboit_draw.js"],"names":[],"mappings":"AAmBA;;;;GAIG;AACH,uDAFU,MAAM,CAE0C;AAwF1D;;;;GAIG;AACH,gDAFU,wBAAwB,CAc/B;AAEH,8EAA8E;AAC9E,6EAA4D;AAE5D,mDAAmD;AACnD,+DAA0D;yCAtIjB,8DAA8D;4CAU3D,mDAAmD;iCAC9D,+BAA+B"}
1
+ {"version":3,"file":"shader_dynamic_mesh_avboit_draw.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/dynamic/shader_dynamic_mesh_avboit_draw.js"],"names":[],"mappings":"AAuBA;;;;;GAKG;AACH,uDAFU,MAAM,CAE0C;AAyF1D;;;;GAIG;AACH,gDAFU,wBAAwB,CAc/B;AAEH,8EAA8E;AAC9E,6EAA4D;AAE5D,mDAAmD;AACnD,+DAA0D;yCA5IjB,8DAA8D;4CAU3D,mDAAmD;iCAC9D,+BAA+B"}
@@ -15,14 +15,19 @@ import { SAMPLER_LINEAR_UPSCALE } from "../texture/SAMPLER_LINEAR_UPSCALE.js";
15
15
  import { VIEW_UNIFORM_STRUCT } from "../view/VIEW_UNIFORM_STRUCT.js";
16
16
  import { VOLUMETRICS_METADATA_STRUCT } from "../volumetrics/VOLUMETRICS_METADATA_STRUCT.js";
17
17
  import { chunk_dynamic_mesh_avboit_vertex } from "./chunk_dynamic_mesh_avboit_vertex.js";
18
- import { DYNAMIC_MESH_RESOURCES } from "./shader_dynamic_mesh.js";
18
+ import {
19
+ DYNAMIC_MESH_BIND_GROUP_DRAWS,
20
+ DYNAMIC_MESH_BIND_GROUP_GEOMETRY,
21
+ DYNAMIC_MESH_RESOURCES
22
+ } from "./shader_dynamic_mesh.js";
19
23
 
20
24
  /**
21
25
  * Bind group of everything the draw reads once per pass — the view, the warp, the integral and the
22
- * fog. Group 0 is the dynamic-mesh group, per mesh.
26
+ * fog. Groups 0 and 1 are the dynamic-mesh groups: the draw constants per chunk, the geometry per
27
+ * mesh.
23
28
  * @type {number}
24
29
  */
25
- export const DYNAMIC_MESH_AVBOIT_DRAW_BIND_GROUP_PASS = 1;
30
+ export const DYNAMIC_MESH_AVBOIT_DRAW_BIND_GROUP_PASS = 2;
26
31
 
27
32
  /**
28
33
  * The dynamic meshes' AVBOIT draw: every mesh's triangles at internal resolution, depth-tested
@@ -42,7 +47,8 @@ export const DYNAMIC_MESH_AVBOIT_DRAW_BIND_GROUP_PASS = 1;
42
47
 
43
48
  const resources = new ShaderResourceSetDescriptor();
44
49
 
45
- resources.addGroup(DYNAMIC_MESH_RESOURCES.groups[0]);
50
+ resources.addGroup(DYNAMIC_MESH_RESOURCES.groups[DYNAMIC_MESH_BIND_GROUP_DRAWS]);
51
+ resources.addGroup(DYNAMIC_MESH_RESOURCES.groups[DYNAMIC_MESH_BIND_GROUP_GEOMETRY]);
46
52
 
47
53
  resources.createGroup()
48
54
  .addUniform("view", VIEW_UNIFORM_STRUCT)
@@ -66,8 +72,8 @@ struct DynamicMeshAVBOITDrawOutput {
66
72
  }
67
73
 
68
74
  @vertex
69
- fn vs_main(@builtin(vertex_index) vi : u32) -> DynamicMeshAVBOITVertexOut {
70
- return dynamic_mesh_avboit_vertex(vi);
75
+ fn vs_main(@builtin(vertex_index) vi : u32, @builtin(instance_index) draw_index : u32) -> DynamicMeshAVBOITVertexOut {
76
+ return dynamic_mesh_avboit_vertex(vi, draw_index);
71
77
  }
72
78
 
73
79
  @fragment
@@ -1,10 +1,11 @@
1
1
  /**
2
- * Bind group of the warp, set once per pass. Group 0 is the dynamic-mesh group, per mesh.
2
+ * Bind group of the warp, set once per pass. Groups 0 and 1 are the dynamic-mesh groups: the draw
3
+ * constants per chunk, the geometry per mesh.
3
4
  * @type {number}
4
5
  */
5
6
  export const DYNAMIC_MESH_AVBOIT_SPLAT_BIND_GROUP_PASS: number;
6
7
  /**
7
- * Bind group of the volume atomics.
8
+ * Bind group of the volume atomics, set once per pass.
8
9
  * @type {number}
9
10
  */
10
11
  export const DYNAMIC_MESH_AVBOIT_SPLAT_BIND_GROUP_VOLUME: number;
@@ -1 +1 @@
1
- {"version":3,"file":"shader_dynamic_mesh_avboit_splat.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/dynamic/shader_dynamic_mesh_avboit_splat.js"],"names":[],"mappings":"AAkBA;;;GAGG;AACH,wDAFU,MAAM,CAE2C;AAE3D;;;GAGG;AACH,0DAFU,MAAM,CAE6C;AAE7D;;;;GAIG;AACH,gDAFU,MAAM,CAEmC;AAuGnD;;;;;;GAMG;AACH,iDAFU,wBAAwB,CAa/B;AAEH,gFAAgF;AAChF,8EAA6D;AAE7D,mDAAmD;AACnD,gEAA2D;yCAjKlB,8DAA8D;4CAU3D,mDAAmD;iCAC9D,+BAA+B"}
1
+ {"version":3,"file":"shader_dynamic_mesh_avboit_splat.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/dynamic/shader_dynamic_mesh_avboit_splat.js"],"names":[],"mappings":"AAsBA;;;;GAIG;AACH,wDAFU,MAAM,CAE2C;AAE3D;;;GAGG;AACH,0DAFU,MAAM,CAE6C;AAE7D;;;;GAIG;AACH,gDAFU,MAAM,CAEmC;AA0GnD;;;;;;GAMG;AACH,iDAFU,wBAAwB,CAa/B;AAEH,gFAAgF;AAChF,8EAA6D;AAE7D,mDAAmD;AACnD,gEAA2D;yCAzKlB,8DAA8D;4CAU3D,mDAAmD;iCAC9D,+BAA+B"}
@@ -14,19 +14,24 @@ import { ShaderDescriptor } from "../shader/ShaderDescriptor.js";
14
14
  import { atomic_u32 } from "../shader/type/WEBGPU_WGSL_PRIMITIVE_TYPES.js";
15
15
  import { WebGPUArray } from "../shader/type/WebGPUArray.js";
16
16
  import { chunk_dynamic_mesh_avboit_vertex } from "./chunk_dynamic_mesh_avboit_vertex.js";
17
- import { DYNAMIC_MESH_RESOURCES } from "./shader_dynamic_mesh.js";
17
+ import {
18
+ DYNAMIC_MESH_BIND_GROUP_DRAWS,
19
+ DYNAMIC_MESH_BIND_GROUP_GEOMETRY,
20
+ DYNAMIC_MESH_RESOURCES
21
+ } from "./shader_dynamic_mesh.js";
18
22
 
19
23
  /**
20
- * Bind group of the warp, set once per pass. Group 0 is the dynamic-mesh group, per mesh.
24
+ * Bind group of the warp, set once per pass. Groups 0 and 1 are the dynamic-mesh groups: the draw
25
+ * constants per chunk, the geometry per mesh.
21
26
  * @type {number}
22
27
  */
23
- export const DYNAMIC_MESH_AVBOIT_SPLAT_BIND_GROUP_PASS = 1;
28
+ export const DYNAMIC_MESH_AVBOIT_SPLAT_BIND_GROUP_PASS = 2;
24
29
 
25
30
  /**
26
- * Bind group of the volume atomics.
31
+ * Bind group of the volume atomics, set once per pass.
27
32
  * @type {number}
28
33
  */
29
- export const DYNAMIC_MESH_AVBOIT_SPLAT_BIND_GROUP_VOLUME = 2;
34
+ export const DYNAMIC_MESH_AVBOIT_SPLAT_BIND_GROUP_VOLUME = 3;
30
35
 
31
36
  /**
32
37
  * Samples per pixel of the splat's raster, which is what a fragment's extinction is weighted by the
@@ -64,13 +69,15 @@ export const DYNAMIC_MESH_AVBOIT_SPLAT_SAMPLES = 4;
64
69
  * reason the meshlet splat has none: a splat behind an opaque surface lies deeper than anything the
65
70
  * draw will look it up for.
66
71
  *
67
- * Group 0 is `DYNAMIC_MESH_RESOURCES`' own group, the same object, so a mesh's bindings are the ones
68
- * its residency already builds for the pass over the scene.
72
+ * Groups 0 and 1 are `DYNAMIC_MESH_RESOURCES`' own groups, the same objects, so their layouts are
73
+ * the ones every dynamic-mesh pipeline declares and a geometry's one group serves them all. The AVBOIT
74
+ * draw binds the same groups this splat does, and reads the same constants: one upload a frame.
69
75
  */
70
76
 
71
77
  const resources = new ShaderResourceSetDescriptor();
72
78
 
73
- resources.addGroup(DYNAMIC_MESH_RESOURCES.groups[0]);
79
+ resources.addGroup(DYNAMIC_MESH_RESOURCES.groups[DYNAMIC_MESH_BIND_GROUP_DRAWS]);
80
+ resources.addGroup(DYNAMIC_MESH_RESOURCES.groups[DYNAMIC_MESH_BIND_GROUP_GEOMETRY]);
74
81
 
75
82
  resources.createGroup()
76
83
  .addStorageBuffer("warp", AVBOIT_WARP_STRUCT);
@@ -83,8 +90,8 @@ const body = CodeChunk.from(
83
90
  //language=WGSL
84
91
  `
85
92
  @vertex
86
- fn vs_main(@builtin(vertex_index) vi : u32) -> DynamicMeshAVBOITVertexOut {
87
- return dynamic_mesh_avboit_vertex(vi);
93
+ fn vs_main(@builtin(vertex_index) vi : u32, @builtin(instance_index) draw_index : u32) -> DynamicMeshAVBOITVertexOut {
94
+ return dynamic_mesh_avboit_vertex(vi, draw_index);
88
95
  }
89
96
 
90
97
  @fragment
@@ -127,11 +134,12 @@ fn fs_main(in : DynamicMeshAVBOITVertexOut, @builtin(sample_mask) sample_mask :
127
134
  const descriptor = ShaderDescriptor.from({ label: "Dynamic Mesh AVBOIT Splat", body, resources });
128
135
 
129
136
  // Built group by group: the atomics are fragment-only, and WebGPU refuses a read-write storage
130
- // buffer that is visible to the vertex stage. The dynamic-mesh group keeps the visibility it has in
131
- // the pass over the scene, so the two layouts agree.
137
+ // buffer that is visible to the vertex stage. The dynamic-mesh groups keep the visibility they have
138
+ // in the pass over the scene, so the layouts agree and one geometry group serves every pipeline.
132
139
  const groups = resources.groups;
133
140
  const layout = PipelineLayoutDescriptor.from([
134
- groups[0].generateBindGroupLayoutDescriptor(GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT),
141
+ groups[DYNAMIC_MESH_BIND_GROUP_DRAWS].generateBindGroupLayoutDescriptor(GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT),
142
+ groups[DYNAMIC_MESH_BIND_GROUP_GEOMETRY].generateBindGroupLayoutDescriptor(GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT),
135
143
  groups[DYNAMIC_MESH_AVBOIT_SPLAT_BIND_GROUP_PASS].generateBindGroupLayoutDescriptor(GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT),
136
144
  groups[DYNAMIC_MESH_AVBOIT_SPLAT_BIND_GROUP_VOLUME].generateBindGroupLayoutDescriptor(GPUShaderStage.FRAGMENT),
137
145
  ], resources.immediateSize);
@@ -13,7 +13,7 @@ export class TinyGltf {
13
13
  * @readonly
14
14
  * @type {TextureFormat}
15
15
  */
16
- static readonly "__#251@#UNCOMPRESSED_TARGET": TextureFormat;
16
+ static readonly "__#252@#UNCOMPRESSED_TARGET": TextureFormat;
17
17
  /**
18
18
  * @param {AssetManager} assetManager
19
19
  * @param {AssetRequestScope} [scope]
@@ -53,7 +53,7 @@ export class NSS {
53
53
  * @returns {number}
54
54
  */
55
55
  static recommended_jitter_sequence_size(upscale_ratio: number): number;
56
- static "__#185@#preprocess_tensor_descriptor"(render_w: any, render_h: any): TextureResourceDescriptor;
56
+ static "__#186@#preprocess_tensor_descriptor"(render_w: any, render_h: any): TextureResourceDescriptor;
57
57
  /**
58
58
  * @param {GraphicsContext} graphics
59
59
  */