@woosh/meep-engine 3.60.7 → 3.60.9

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 (126) hide show
  1. package/package.json +1 -1
  2. package/src/engine/graphics3/AnimationGraphSystem.d.ts +4 -1
  3. package/src/engine/graphics3/AnimationGraphSystem.d.ts.map +1 -1
  4. package/src/engine/graphics3/AnimationGraphSystem.js +35 -5
  5. package/src/engine/graphics3/AnimationSystem.d.ts +1 -1
  6. package/src/engine/graphics3/AnimationSystem.d.ts.map +1 -1
  7. package/src/engine/graphics3/AnimationSystem.js +34 -5
  8. package/src/engine/graphics3/FoliageWindSystem.d.ts +2 -1
  9. package/src/engine/graphics3/FoliageWindSystem.d.ts.map +1 -1
  10. package/src/engine/graphics3/FoliageWindSystem.js +50 -3
  11. package/src/engine/graphics3/GPUFluidSystem.d.ts.map +1 -1
  12. package/src/engine/graphics3/GPUFluidSystem.js +16 -14
  13. package/src/engine/graphics3/GPUParticleEmitterSystem.d.ts +2 -2
  14. package/src/engine/graphics3/GPUParticleEmitterSystem.d.ts.map +1 -1
  15. package/src/engine/graphics3/GPUParticleEmitterSystem.js +84 -32
  16. package/src/engine/graphics3/LightSystem.d.ts +4 -0
  17. package/src/engine/graphics3/LightSystem.d.ts.map +1 -1
  18. package/src/engine/graphics3/LightSystem.js +23 -6
  19. package/src/engine/graphics3/MeshSkinSystem.d.ts +1 -1
  20. package/src/engine/graphics3/MeshSkinSystem.d.ts.map +1 -1
  21. package/src/engine/graphics3/MeshSkinSystem.js +50 -5
  22. package/src/engine/graphics3/MeshSystem.d.ts +1 -0
  23. package/src/engine/graphics3/MeshSystem.d.ts.map +1 -1
  24. package/src/engine/graphics3/MeshSystem.js +22 -8
  25. package/src/engine/graphics3/ShadedGeometrySystem.d.ts +5 -1
  26. package/src/engine/graphics3/ShadedGeometrySystem.d.ts.map +1 -1
  27. package/src/engine/graphics3/ShadedGeometrySystem.js +56 -7
  28. package/src/engine/graphics3/WaterSystem.d.ts +3 -0
  29. package/src/engine/graphics3/WaterSystem.d.ts.map +1 -1
  30. package/src/engine/graphics3/WaterSystem.js +10 -2
  31. package/src/engine/graphics3/animation/AnimationClipsSink.d.ts +15 -7
  32. package/src/engine/graphics3/animation/AnimationClipsSink.d.ts.map +1 -1
  33. package/src/engine/graphics3/animation/AnimationClipsSink.js +42 -8
  34. package/src/engine/network/state/ReplicationSlotTable.d.ts +9 -5
  35. package/src/engine/network/state/ReplicationSlotTable.d.ts.map +1 -1
  36. package/src/engine/network/state/ReplicationSlotTable.js +36 -8
  37. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  38. package/src/generation/markers/GridActionRuleSet.d.ts.map +1 -1
  39. package/src/generation/markers/GridActionRuleSet.js +12 -3
  40. package/src/shade/renderer/GraphicsContext.d.ts +8 -0
  41. package/src/shade/renderer/GraphicsContext.d.ts.map +1 -1
  42. package/src/shade/renderer/GraphicsContext.js +29 -0
  43. package/src/shade/renderer/Renderer.d.ts +10 -0
  44. package/src/shade/renderer/Renderer.d.ts.map +1 -1
  45. package/src/shade/renderer/Renderer.js +22 -2
  46. package/src/shade/renderer/fluid/GPUFluidCascade.d.ts +3 -3
  47. package/src/shade/renderer/fluid/GPUFluidCascadeStack.d.ts +1 -1
  48. package/src/shade/renderer/fluid/forcing/GPUFluidForcing.d.ts +6 -6
  49. package/src/shade/renderer/fluid/pressure/GPUFluidPressureSolve.d.ts +1 -1
  50. package/src/shade/renderer/fluid/query/GPUFluidQueries.d.ts +1 -1
  51. package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.d.ts +1 -1
  52. package/src/shade/renderer/light/GPULightCollection.d.ts +3 -1
  53. package/src/shade/renderer/light/GPULightCollection.d.ts.map +1 -1
  54. package/src/shade/renderer/light/GPULightCollection.js +34 -9
  55. package/src/shade/renderer/light/LightCollection.d.ts +13 -3
  56. package/src/shade/renderer/light/LightCollection.d.ts.map +1 -1
  57. package/src/shade/renderer/light/LightCollection.js +19 -3
  58. package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +1 -1
  59. package/src/shade/renderer/material/GPUMaterialManager.d.ts +22 -0
  60. package/src/shade/renderer/material/GPUMaterialManager.d.ts.map +1 -1
  61. package/src/shade/renderer/material/GPUMaterialManager.js +30 -0
  62. package/src/shade/renderer/material/dispatch/GPUMaterialComputeDispatch.d.ts +75 -0
  63. package/src/shade/renderer/material/dispatch/GPUMaterialComputeDispatch.d.ts.map +1 -0
  64. package/src/shade/renderer/material/dispatch/GPUMaterialComputeDispatch.js +338 -0
  65. package/src/shade/renderer/material/dispatch/MATERIAL_DISPATCH_CONSTANTS.d.ts +50 -0
  66. package/src/shade/renderer/material/dispatch/MATERIAL_DISPATCH_CONSTANTS.d.ts.map +1 -0
  67. package/src/shade/renderer/material/dispatch/MATERIAL_DISPATCH_CONSTANTS.js +54 -0
  68. package/src/shade/renderer/material/dispatch/MaterialDispatch.d.ts +37 -0
  69. package/src/shade/renderer/material/dispatch/MaterialDispatch.d.ts.map +1 -0
  70. package/src/shade/renderer/material/dispatch/MaterialDispatch.js +31 -0
  71. package/src/shade/renderer/material/dispatch/MaterialDispatchRecords.d.ts +42 -0
  72. package/src/shade/renderer/material/dispatch/MaterialDispatchRecords.d.ts.map +1 -0
  73. package/src/shade/renderer/material/dispatch/MaterialDispatchRecords.js +132 -0
  74. package/src/shade/renderer/material/dispatch/chunk_material_mesh_key.d.ts +21 -0
  75. package/src/shade/renderer/material/dispatch/chunk_material_mesh_key.d.ts.map +1 -0
  76. package/src/shade/renderer/material/dispatch/chunk_material_mesh_key.js +46 -0
  77. package/src/shade/renderer/material/dispatch/chunk_material_quad_keys.d.ts +20 -0
  78. package/src/shade/renderer/material/dispatch/chunk_material_quad_keys.d.ts.map +1 -0
  79. package/src/shade/renderer/material/dispatch/chunk_material_quad_keys.js +111 -0
  80. package/src/shade/renderer/material/dispatch/chunk_material_quad_pack.d.ts +18 -0
  81. package/src/shade/renderer/material/dispatch/chunk_material_quad_pack.d.ts.map +1 -0
  82. package/src/shade/renderer/material/dispatch/chunk_material_quad_pack.js +33 -0
  83. package/src/shade/renderer/material/dispatch/gbuffer_compute.d.ts +116 -0
  84. package/src/shade/renderer/material/dispatch/gbuffer_compute.d.ts.map +1 -0
  85. package/src/shade/renderer/material/dispatch/gbuffer_compute.js +249 -0
  86. package/src/shade/renderer/material/dispatch/graph_material_dispatch_compute.d.ts +56 -0
  87. package/src/shade/renderer/material/dispatch/graph_material_dispatch_compute.d.ts.map +1 -0
  88. package/src/shade/renderer/material/dispatch/graph_material_dispatch_compute.js +315 -0
  89. package/src/shade/renderer/material/dispatch/shader_material_dispatch_commands.d.ts +16 -0
  90. package/src/shade/renderer/material/dispatch/shader_material_dispatch_commands.d.ts.map +1 -0
  91. package/src/shade/renderer/material/dispatch/shader_material_dispatch_commands.js +83 -0
  92. package/src/shade/renderer/material/dispatch/shader_material_pixel_count.d.ts +22 -0
  93. package/src/shade/renderer/material/dispatch/shader_material_pixel_count.d.ts.map +1 -0
  94. package/src/shade/renderer/material/dispatch/shader_material_pixel_count.js +133 -0
  95. package/src/shade/renderer/material/dispatch/shader_material_pixel_scatter.d.ts +14 -0
  96. package/src/shade/renderer/material/dispatch/shader_material_pixel_scatter.d.ts.map +1 -0
  97. package/src/shade/renderer/material/dispatch/shader_material_pixel_scatter.js +98 -0
  98. package/src/shade/renderer/material/standard/VT_MATERIAL_TEMPLATE.d.ts +1 -0
  99. package/src/shade/renderer/material/standard/VT_MATERIAL_TEMPLATE.d.ts.map +1 -1
  100. package/src/shade/renderer/material/standard/VT_MATERIAL_TEMPLATE.js +11 -0
  101. package/src/shade/renderer/material/standard/fragment_gbuffer.d.ts +41 -6
  102. package/src/shade/renderer/material/standard/fragment_gbuffer.d.ts.map +1 -1
  103. package/src/shade/renderer/material/standard/fragment_gbuffer.js +88 -29
  104. package/src/shade/renderer/material/template/ShadeMaterialTemplate.d.ts +13 -1
  105. package/src/shade/renderer/material/template/ShadeMaterialTemplate.d.ts.map +1 -1
  106. package/src/shade/renderer/material/template/ShadeMaterialTemplate.js +18 -1
  107. package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
  108. package/src/shade/renderer/scene/GPUSceneContext.d.ts +6 -0
  109. package/src/shade/renderer/scene/GPUSceneContext.d.ts.map +1 -1
  110. package/src/shade/renderer/scene/GPUSceneContext.js +17 -7
  111. package/src/shade/renderer/scene/Scene.d.ts +4 -3
  112. package/src/shade/renderer/scene/Scene.d.ts.map +1 -1
  113. package/src/shade/renderer/scene/Scene.js +54 -53
  114. package/src/shade/renderer/scene/rows/GPUSceneRows.d.ts +16 -0
  115. package/src/shade/renderer/scene/rows/GPUSceneRows.d.ts.map +1 -1
  116. package/src/shade/renderer/scene/rows/GPUSceneRows.js +34 -0
  117. package/src/shade/renderer/shader/chunk/geometry/normal/chunk_anti_alias_roughness_kaplanyan.d.ts +19 -0
  118. package/src/shade/renderer/shader/chunk/geometry/normal/chunk_anti_alias_roughness_kaplanyan.d.ts.map +1 -1
  119. package/src/shade/renderer/shader/chunk/geometry/normal/chunk_anti_alias_roughness_kaplanyan.js +55 -20
  120. package/src/shade/renderer/shader/chunk/subgroup/chunk_subgroup_keyed_append.d.ts +31 -0
  121. package/src/shade/renderer/shader/chunk/subgroup/chunk_subgroup_keyed_append.d.ts.map +1 -0
  122. package/src/shade/renderer/shader/chunk/subgroup/chunk_subgroup_keyed_append.js +77 -0
  123. package/src/shade/renderer/texture/virtual/VirtualTextureManager.d.ts +6 -0
  124. package/src/shade/renderer/texture/virtual/VirtualTextureManager.d.ts.map +1 -1
  125. package/src/shade/renderer/texture/virtual/VirtualTextureManager.js +15 -1
  126. package/src/shade/renderer/water/query/GPUWaterQueries.d.ts +1 -1
@@ -12,8 +12,9 @@ import { assert } from "../../../core/assert.js";
12
12
  * match the live `(network_id=5, generation=3)` slot, so use-after-free can
13
13
  * be detected at parse time on the receiving peer.
14
14
  *
15
- * Storage is two parallel typed arrays indexed by `network_id`, plus a small
16
- * free-list of reusable IDs. No JS object per slot.
15
+ * Storage is three parallel typed arrays indexed by `network_id` (entity,
16
+ * generation, index in the free list), plus a free-list of reusable IDs.
17
+ * No JS object per slot.
17
18
  *
18
19
  * @author Alex Goldring
19
20
  * @copyright Company Named Limited (c) 2026
@@ -28,6 +29,7 @@ export class ReplicationSlotTable {
28
29
  * @private
29
30
  */
30
31
  #free_list = [];
32
+ #free_position_by_network;
31
33
  /**
32
34
  * Highest network_id ever assigned.
33
35
  * @type {number}
@@ -54,6 +56,13 @@ export class ReplicationSlotTable {
54
56
  */
55
57
  this.#generation_by_network = new Uint32Array(initial_capacity);
56
58
 
59
+ /**
60
+ * Index of each network_id in `#free_list`, or -1 if it is not on it.
61
+ * @type {Int32Array}
62
+ * @private
63
+ */
64
+ this.#free_position_by_network = new Int32Array(initial_capacity).fill(-1);
65
+
57
66
  /**
58
67
  * Reverse map for entity_id -> network_id lookup.
59
68
  * Sparse; only populated for live mappings.
@@ -85,6 +94,7 @@ export class ReplicationSlotTable {
85
94
  let network_id;
86
95
  if (this.#free_list.length > 0) {
87
96
  network_id = this.#free_list.pop();
97
+ this.#free_position_by_network[network_id] = -1;
88
98
  } else {
89
99
  network_id = this.#highwater++;
90
100
  if (network_id >= this.#capacity) {
@@ -99,8 +109,10 @@ export class ReplicationSlotTable {
99
109
 
100
110
  /**
101
111
  * Allocate using an explicit network_id (for the receiving peer that takes its
102
- * IDs from the wire). Bumps the slot's generation if it was reused. Throws
103
- * if the slot is currently in use.
112
+ * IDs from the wire). The id may be one this peer freed and the sender has
113
+ * since recycled; it is taken off the free list, so {@link allocate} will not
114
+ * hand it out. The slot keeps the generation {@link free} gave it. Throws if
115
+ * the slot is currently in use.
104
116
  *
105
117
  * @param {number} network_id
106
118
  * @param {number} entity_id
@@ -117,9 +129,16 @@ export class ReplicationSlotTable {
117
129
  if (this.#network_id_by_entity.has(entity_id)) {
118
130
  throw new Error(`ReplicationSlotTable.allocate_at: entity ${entity_id} already has network_id ${this.#network_id_by_entity.get(entity_id)}`);
119
131
  }
120
- // Catch the "id is on the free list" case before silent clobbering: a
121
- // subsequent allocate() would pop the same id and overwrite this mapping.
122
- assert.arrayHasNo(this.#free_list, network_id, `ReplicationSlotTable.allocate_at: network_id ${network_id} is in the free list`);
132
+ const free_position = this.#free_position_by_network[network_id];
133
+ if (free_position !== -1) {
134
+ // swap-remove: the last entry fills the hole
135
+ const last = this.#free_list.pop();
136
+ if (last !== network_id) {
137
+ this.#free_list[free_position] = last;
138
+ this.#free_position_by_network[last] = free_position;
139
+ }
140
+ this.#free_position_by_network[network_id] = -1;
141
+ }
123
142
  this.#entity_id_by_network[network_id] = entity_id;
124
143
  this.#network_id_by_entity.set(entity_id, network_id);
125
144
  if (network_id >= this.#highwater) this.#highwater = network_id + 1;
@@ -127,12 +146,16 @@ export class ReplicationSlotTable {
127
146
 
128
147
  /**
129
148
  * Free the slot for `network_id`. Bumps the slot's generation. Slot becomes
130
- * available for re-allocation.
149
+ * available for re-allocation. Freeing a slot that is not in use, including
150
+ * one past the table's storage, does nothing.
131
151
  *
132
152
  * @param {number} network_id
133
153
  */
134
154
  free(network_id) {
135
155
  assert.isNonNegativeInteger(network_id, 'network_id');
156
+ if (network_id >= this.#capacity) {
157
+ return; // never allocated
158
+ }
136
159
  const entity_id = this.#entity_id_by_network[network_id];
137
160
  if (entity_id === -1) {
138
161
  return; // already free
@@ -140,6 +163,7 @@ export class ReplicationSlotTable {
140
163
  this.#entity_id_by_network[network_id] = -1;
141
164
  this.#network_id_by_entity.delete(entity_id);
142
165
  this.#generation_by_network[network_id] = (this.#generation_by_network[network_id] + 1) >>> 0;
166
+ this.#free_position_by_network[network_id] = this.#free_list.length;
143
167
  this.#free_list.push(network_id);
144
168
  }
145
169
 
@@ -199,8 +223,12 @@ export class ReplicationSlotTable {
199
223
  const new_generations = new Uint32Array(new_capacity);
200
224
  new_generations.set(this.#generation_by_network);
201
225
 
226
+ const new_free_positions = new Int32Array(new_capacity).fill(-1);
227
+ new_free_positions.set(this.#free_position_by_network);
228
+
202
229
  this.#entity_id_by_network = new_entities;
203
230
  this.#generation_by_network = new_generations;
231
+ this.#free_position_by_network = new_free_positions;
204
232
  this.#capacity = new_capacity;
205
233
  }
206
234
  }
@@ -66,11 +66,11 @@ export class FluidObstacleSystem extends System<any> {
66
66
  /**
67
67
  * @param {FluidComponent} fluid
68
68
  */
69
- static "__#483@#refresh_masks"(fluid: FluidComponent): void;
69
+ static "__#485@#refresh_masks"(fluid: FluidComponent): void;
70
70
  /**
71
71
  * @param {FluidComponent} fluid
72
72
  */
73
- static "__#483@#clear_field"(fluid: FluidComponent): void;
73
+ static "__#485@#clear_field"(fluid: FluidComponent): void;
74
74
  /**
75
75
  * Mark every cell of `fluid` whose centre lies within `inflation` of the
76
76
  * posed shape as solid. Iteration is clipped to the shape's world AABB
@@ -82,7 +82,7 @@ export class FluidObstacleSystem extends System<any> {
82
82
  * @param {number} inflation world-units SDF threshold
83
83
  * @param {Float64Array} point length-3 scratch
84
84
  */
85
- static "__#483@#voxelize"(fluid: FluidComponent, posed: PosedShape3D, aabb: Float64Array, inflation: number, point: Float64Array): void;
85
+ static "__#485@#voxelize"(fluid: FluidComponent, posed: PosedShape3D, aabb: Float64Array, inflation: number, point: Float64Array): void;
86
86
  /**
87
87
  * Write the obstacle's translation velocity onto every face of every cell
88
88
  * it voxelized — the moving-wall boundary condition. Runs AFTER the mask
@@ -102,7 +102,7 @@ export class FluidObstacleSystem extends System<any> {
102
102
  * @param {number} wvy
103
103
  * @param {number} wvz
104
104
  */
105
- static "__#483@#stamp_wall_velocity"(fluid: FluidComponent, posed: PosedShape3D, aabb: Float64Array, inflation: number, point: Float64Array, wvx: number, wvy: number, wvz: number): void;
105
+ static "__#485@#stamp_wall_velocity"(fluid: FluidComponent, posed: PosedShape3D, aabb: Float64Array, inflation: number, point: Float64Array, wvx: number, wvy: number, wvz: number): void;
106
106
  constructor();
107
107
  dependencies: (typeof FluidObstacle)[];
108
108
  components_used: (ResourceAccessSpecification<typeof Transform64> | ResourceAccessSpecification<typeof FluidObstacle> | ResourceAccessSpecification<typeof Collider> | ResourceAccessSpecification<typeof RigidBody> | ResourceAccessSpecification<typeof FluidComponent>)[];
@@ -1 +1 @@
1
- {"version":3,"file":"GridActionRuleSet.d.ts","sourceRoot":"","sources":["../../../../src/generation/markers/GridActionRuleSet.js"],"names":[],"mappings":"AA2BA;IA0BI;;;;;;;;OAQG;IACH;QAN4C,KAAK,EAAtC,uBAAuB;QACW,MAAM,GAAxC,uBAAuB;QACJ,OAAO,GAA1B,MAAM,EAAE;QACU,kBAAkB,GAApC,OAAO;QACL,iBAAiB,CAkB7B;IAjDD;;;OAGG;IACH,UAFU,uBAAuB,CAEnB;IAEd;;;OAGG;IACH,QAFU,uBAAuB,GAAC,MAAM,CAEI;IAE5C;;;OAGG;IACH,SAFU,MAAM,EAAE,CAED;IAEjB;;;OAGG;IACH,aAFU,OAAO,CAEE;IA6BnB;;;OAGG;IACH,uCAEC;IAED;;;;;;OAMG;IACH,8BAJW,MAAM,eACN,MAAM,QAiIhB;CACJ;wCArNuC,8BAA8B"}
1
+ {"version":3,"file":"GridActionRuleSet.d.ts","sourceRoot":"","sources":["../../../../src/generation/markers/GridActionRuleSet.js"],"names":[],"mappings":"AA4BA;IA0BI;;;;;;;;OAQG;IACH;QAN4C,KAAK,EAAtC,uBAAuB;QACW,MAAM,GAAxC,uBAAuB;QACJ,OAAO,GAA1B,MAAM,EAAE;QACU,kBAAkB,GAApC,OAAO;QACL,iBAAiB,CAkB7B;IAjDD;;;OAGG;IACH,UAFU,uBAAuB,CAEnB;IAEd;;;OAGG;IACH,QAFU,uBAAuB,GAAC,MAAM,CAEI;IAE5C;;;OAGG;IACH,SAFU,MAAM,EAAE,CAED;IAEjB;;;OAGG;IACH,aAFU,OAAO,CAEE;IA6BnB;;;OAGG;IACH,uCAEC;IAED;;;;;;OAMG;IACH,8BAJW,MAAM,eACN,MAAM,QAyIhB;CACJ;wCA7NuC,8BAA8B"}
@@ -3,6 +3,7 @@ import { ArrayIteratorRandom } from "../../core/collection/array/iterator/ArrayI
3
3
  import { ArrayIteratorSequential } from "../../core/collection/array/iterator/ArrayIteratorSequential.js";
4
4
  import { v2_rotate } from "../../core/geom/vec2/v2_rotate.js";
5
5
  import { PI_HALF } from "../../core/math/PI_HALF.js";
6
+ import { randomIntegerBetween } from "../../core/math/random/randomIntegerBetween.js";
6
7
  import { seededRandom } from "../../core/math/random/seededRandom.js";
7
8
  import TaskGroup from "../../core/process/task/TaskGroup.js";
8
9
  import { countTask } from "../../core/process/task/util/countTask.js";
@@ -146,7 +147,6 @@ export class GridActionRuleSet {
146
147
 
147
148
  const tMain = randomCountTask(seed, 0, sampleCount, index => {
148
149
 
149
-
150
150
  const sample_y = (index / sampleCountX) | 0;
151
151
  const sample_x = index % sampleCountX;
152
152
 
@@ -166,11 +166,19 @@ export class GridActionRuleSet {
166
166
 
167
167
  const matcher = element.pattern;
168
168
 
169
+ let ROTATION_COUNT = 1;
170
+ let INITIAL_ROTATION = 0;
171
+
172
+ if (element.allowRotation) {
173
+ ROTATION_COUNT = 4;
174
+ // to avoid biasing rotation 0, we pick a random initial rotation; the sequence is always the same though
175
+ INITIAL_ROTATION = randomIntegerBetween(random, 0, 3);
176
+ }
177
+
169
178
  sampling_loop: for (let sampleIndex = 0; sampleIndex < patternSize;) {
170
179
  const sampleOffsetX = pattern[sampleIndex++];
171
180
  const sampleOffsetY = pattern[sampleIndex++];
172
181
 
173
- const ROTATION_COUNT = element.allowRotation ? 4 : 1;
174
182
 
175
183
  // a single roll per placement attempt: whether the rule fires is decided once,
176
184
  // the rotation scan only decides the orientation. Rolling per rotation would
@@ -178,8 +186,9 @@ export class GridActionRuleSet {
178
186
  const roll = random();
179
187
 
180
188
  for (let j = 0; j < ROTATION_COUNT; j++) {
189
+ const rotation_index = (j + INITIAL_ROTATION) % 4;
181
190
 
182
- const rotation = j * PI_HALF;
191
+ const rotation = rotation_index * PI_HALF;
183
192
 
184
193
  v2_rotate(scratch_offset, 0, sampleOffsetX, sampleOffsetY, rotation);
185
194
 
@@ -17,6 +17,13 @@ export class GraphicsContext {
17
17
  * @returns {GPUResidentMaterialContext}
18
18
  */
19
19
  get materials_resident(): GPUResidentMaterialContext;
20
+ /**
21
+ * The G-buffer pass as {@link MaterialDispatch.Compute} runs it, over {@link materials}. Made on
22
+ * first use: a renderer on the default dispatch never makes it.
23
+ *
24
+ * @returns {GPUMaterialComputeDispatch}
25
+ */
26
+ get materials_compute(): GPUMaterialComputeDispatch;
20
27
  /**
21
28
  *
22
29
  * @return {GPUCollectionLimits}
@@ -156,6 +163,7 @@ import { GPUGeometryManager } from "./geometry/GPUGeometryManager.js";
156
163
  import { GPUMaterialManager } from "./material/GPUMaterialManager.js";
157
164
  import { GPUSamplerManager } from "./GPUSamplerManager.js";
158
165
  import { GPUResidentMaterialContext } from "./material/resident/GPUResidentMaterialContext.js";
166
+ import { GPUMaterialComputeDispatch } from "./material/dispatch/GPUMaterialComputeDispatch.js";
159
167
  import { GPUCollectionLimits } from "./rasterize/expand/GPUCollectionLimits.js";
160
168
  import { PipelineLayoutManager } from "../device/pipeline/PipelineLayoutManager.js";
161
169
  import { RenderPipelineManager } from "../device/pipeline/RenderPipelineManager.js";
@@ -1 +1 @@
1
- {"version":3,"file":"GraphicsContext.d.ts","sourceRoot":"","sources":["../../../../src/shade/renderer/GraphicsContext.js"],"names":[],"mappings":"AAmCA;IAqKI,yBAiCC;IArMD;;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,uBAQC;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,QA2B9D;IAED;;;;;;;;;OASG;IACH,8DAJW,sBAAsB,SACtB,MAAM,aACN,oBAAoB,QA0C9B;IAED;;;;OAIG;IACH,gCAHW,gBAAgB,GACd,gBAAgB,CAI5B;IAED;;OAEG;IACH,+BAgBC;IAED,4BAEC;IAED,eAoDC;IAED;;;;;;OAMG;IACH,gBAsBC;IAGL;;;OAGG;IACH,4BAFU,OAAO,CAE0B;;CAN1C;+BA9ZY,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"}
1
+ {"version":3,"file":"GraphicsContext.d.ts","sourceRoot":"","sources":["../../../../src/shade/renderer/GraphicsContext.js"],"names":[],"mappings":"AAoCA;IA6LI,yBAiCC;IA7ND;;OAEG;IACH,YAFU,kBAAkB,CAEjB;IAEX;;OAEG;IACH,WAFU,kBAAkB,CAElB;IAYV;;OAEG;IACH,UAFU,iBAAiB,CAElB;IAET;;;OAGG;IACH,qDAOC;IAED;;;;;OAKG;IACH,oDAWC;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,uBAQC;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,QA2B9D;IAED;;;;;;;;;OASG;IACH,8DAJW,sBAAsB,SACtB,MAAM,aACN,oBAAoB,QA0C9B;IAED;;;;OAIG;IACH,gCAHW,gBAAgB,GACd,gBAAgB,CAI5B;IAED;;OAEG;IACH,+BAgBC;IAED,4BAEC;IAED,eAoDC;IAED;;;;;;OAMG;IACH,gBA0BC;IAGL;;;OAGG;IACH,4BAFU,OAAO,CAE0B;;CAN1C;+BA1bY,OAAO,0CAA0C,EAAE,gBAAgB;qCACnE,OAAO,kDAAkD,EAAE,sBAAsB;2BAKjF,OAAO,mCAAmC,EAAE,YAAY;mCAlBlC,kCAAkC;mCAGlC,kCAAkC;kCADnC,wBAAwB;2CAGf,mDAAmD;2CADnD,mDAAmD;oCAH1D,2CAA2C;sCAbzC,6CAA6C;sCAC7C,6CAA6C;uCAF5C,8CAA8C;qCAIhD,0CAA0C;+BAiBhD,6BAA6B;sCACtB,4CAA4C;iCAhBjD,+BAA+B;mCAC7B,gCAAgC;yCAC1B,sCAAsC;0CAGrC,uCAAuC;yCACxC,sCAAsC;2CAFpC,wCAAwC;oCAU/C,kCAAkC;iCAXtB,8BAA8B"}
@@ -16,6 +16,7 @@ import { GPUGeometryManager } from "./geometry/GPUGeometryManager.js";
16
16
  import { GPUCollectionLimits } from "./rasterize/expand/GPUCollectionLimits.js";
17
17
  import { GPUSamplerManager } from "./GPUSamplerManager.js";
18
18
  import { GPUMaterialManager } from "./material/GPUMaterialManager.js";
19
+ import { GPUMaterialComputeDispatch } from "./material/dispatch/GPUMaterialComputeDispatch.js";
19
20
  import { GPUResidentMaterialContext } from "./material/resident/GPUResidentMaterialContext.js";
20
21
  import { STATIC_GRAPHICS_ENGINE_ASSETS } from "./STATIC_GRAPHICS_ENGINE_ASSETS.js";
21
22
  import { GPUTextureAllocator } from "./texture/GPUTextureAllocator.js";
@@ -49,6 +50,11 @@ export class GraphicsContext {
49
50
  */
50
51
  #materials_resident
51
52
 
53
+ /**
54
+ * @type {GPUMaterialComputeDispatch|undefined}
55
+ */
56
+ #materials_compute = undefined;
57
+
52
58
  /**
53
59
  * @type {GPUSamplerManager}
54
60
  */
@@ -67,6 +73,25 @@ export class GraphicsContext {
67
73
  return this.#materials_resident;
68
74
  }
69
75
 
76
+ /**
77
+ * The G-buffer pass as {@link MaterialDispatch.Compute} runs it, over {@link materials}. Made on
78
+ * first use: a renderer on the default dispatch never makes it.
79
+ *
80
+ * @returns {GPUMaterialComputeDispatch}
81
+ */
82
+ get materials_compute() {
83
+ if (this.#materials_compute === undefined) {
84
+ this.#materials_compute = new GPUMaterialComputeDispatch({
85
+ device: this.#device,
86
+ materials: this.materials,
87
+ compute_pipelines: this.compute_pipelines,
88
+ bindings: this.bind_groups,
89
+ });
90
+ }
91
+
92
+ return this.#materials_compute;
93
+ }
94
+
70
95
  /**
71
96
  * @type {GPUCollectionLimits}
72
97
  */
@@ -421,6 +446,10 @@ export class GraphicsContext {
421
446
 
422
447
  this.materials.destroy();
423
448
 
449
+ if (this.#materials_compute !== undefined) {
450
+ this.#materials_compute.destroy();
451
+ }
452
+
424
453
  if (this.#materials_resident !== undefined) {
425
454
  this.#materials_resident.destroy();
426
455
  }
@@ -29,6 +29,15 @@ export class Renderer {
29
29
  * @type {ShadeIndirectLightingMode}
30
30
  */
31
31
  indirect_lighting_mode: ShadeIndirectLightingMode;
32
+ /**
33
+ * How the G-buffer pass runs each material over its pixels of the visibility buffer — see
34
+ * {@link MaterialDispatch}. Read when a frame is recorded, so it can change between any two.
35
+ * Both run the same laydown. {@link MaterialDispatch.Compute} is experimental and slower on
36
+ * high-end GPUs; leave this on {@link MaterialDispatch.Quad} unless measuring it.
37
+ *
38
+ * @type {MaterialDispatch}
39
+ */
40
+ material_dispatch: MaterialDispatch;
32
41
  /**
33
42
  * Settings of {@link ShadeIndirectLightingMode.ProbeClipmap}, read every frame it runs. A change to
34
43
  * one of its structural fields builds the mode's clipmaps again; see {@link ProbeClipmapSettings}.
@@ -567,6 +576,7 @@ export type GPUSceneContext = import("./scene/GPUSceneContext.js").GPUSceneConte
567
576
  export type Scene = import("./scene/Scene.js").Scene;
568
577
  import { SceneManager } from "./scene/SceneManager.js";
569
578
  import { ShadeIndirectLightingMode } from "./ShadeIndirectLightingMode.js";
579
+ import { MaterialDispatch } from "./material/dispatch/MaterialDispatch.js";
570
580
  import { ProbeClipmapSettings } from "./global_illumination/probe_clipmap/ProbeClipmapSettings.js";
571
581
  import { ShadeTransparencyMode } from "./ShadeTransparencyMode.js";
572
582
  import { ShadeToneMappingMode } from "./ShadeToneMappingMode.js";
@@ -1 +1 @@
1
- {"version":3,"file":"Renderer.d.ts","sourceRoot":"","sources":["../../../../src/shade/renderer/Renderer.js"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Renderer.d.ts","sourceRoot":"","sources":["../../../../src/shade/renderer/Renderer.js"],"names":[],"mappings":"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"}
@@ -101,6 +101,7 @@ import { ReSTIRDI } from "./restir/di/ReSTIRDI.js";
101
101
  import { GPUParticleSystem } from "./particles/GPUParticleSystem.js";
102
102
  import { SceneManager } from "./scene/SceneManager.js";
103
103
  import { ShadeIndirectLightingMode } from "./ShadeIndirectLightingMode.js";
104
+ import { MaterialDispatch } from "./material/dispatch/MaterialDispatch.js";
104
105
  import { ShadeToneMappingMode } from "./ShadeToneMappingMode.js";
105
106
  import { ShadeTransparencyMode } from "./ShadeTransparencyMode.js";
106
107
  import { AVBOITSettings } from "./rasterize/native/avboit/AVBOITSettings.js";
@@ -228,6 +229,16 @@ export class Renderer {
228
229
  */
229
230
  indirect_lighting_mode = ShadeIndirectLightingMode.IBL;
230
231
 
232
+ /**
233
+ * How the G-buffer pass runs each material over its pixels of the visibility buffer — see
234
+ * {@link MaterialDispatch}. Read when a frame is recorded, so it can change between any two.
235
+ * Both run the same laydown. {@link MaterialDispatch.Compute} is experimental and slower on
236
+ * high-end GPUs; leave this on {@link MaterialDispatch.Quad} unless measuring it.
237
+ *
238
+ * @type {MaterialDispatch}
239
+ */
240
+ material_dispatch = MaterialDispatch.Quad;
241
+
231
242
  /**
232
243
  * Settings of {@link ShadeIndirectLightingMode.ProbeClipmap}, read every frame it runs. A change to
233
244
  * one of its structural fields builds the mode's clipmaps again; see {@link ProbeClipmapSettings}.
@@ -1855,7 +1866,8 @@ export class Renderer {
1855
1866
  size: resolution_internal,
1856
1867
  format: G_BUFFER_COLOR_TARGETS[1].format,
1857
1868
  mipLevelCount: 1,
1858
- usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING,
1869
+ // storage too, for the compute material dispatch, which can be chosen on any frame
1870
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.STORAGE_BINDING,
1859
1871
  }));
1860
1872
  }
1861
1873
 
@@ -1930,6 +1942,10 @@ export class Renderer {
1930
1942
  const color_formats = [deferred_shader.pipeline.fragment.targets[0].format];
1931
1943
 
1932
1944
  graphics.materials.enquirePipelines(enquiry);
1945
+
1946
+ if (this.material_dispatch === MaterialDispatch.Compute) {
1947
+ graphics.materials_compute.enquirePipelines(enquiry);
1948
+ }
1933
1949
  this.#scenes.enquirePipelines(enquiry);
1934
1950
 
1935
1951
  enquire_rasterize_scene_pipelines(enquiry, viz_rasterization_opaque_pass_descriptor, CullPolicy.Standard);
@@ -2784,7 +2800,11 @@ export class Renderer {
2784
2800
  }
2785
2801
 
2786
2802
  // run materials
2787
- const mat_g = graphics.materials.graph_viz_render({
2803
+ const material_pass = this.material_dispatch === MaterialDispatch.Compute
2804
+ ? graphics.materials_compute
2805
+ : graphics.materials;
2806
+
2807
+ const mat_g = material_pass.graph_viz_render({
2788
2808
  graph,
2789
2809
  view: view_ctx,
2790
2810
  texture_viz_mesh: gr_viz_buffer_mesh,
@@ -143,7 +143,7 @@ export class GPUFluidCascade {
143
143
  * @param {*} _resources
144
144
  * @param {{encoder: ShadeGPUCommandContext}} context
145
145
  */
146
- static "__#281@#execute_restrict"(record: object, _resources: any, context: {
146
+ static "__#283@#execute_restrict"(record: object, _resources: any, context: {
147
147
  encoder: ShadeGPUCommandContext;
148
148
  }): void;
149
149
  /**
@@ -151,7 +151,7 @@ export class GPUFluidCascade {
151
151
  * @param {*} _resources
152
152
  * @param {{encoder: ShadeGPUCommandContext}} context
153
153
  */
154
- static "__#281@#execute_fill"(record: object, _resources: any, context: {
154
+ static "__#283@#execute_fill"(record: object, _resources: any, context: {
155
155
  encoder: ShadeGPUCommandContext;
156
156
  }): void;
157
157
  /**
@@ -159,7 +159,7 @@ export class GPUFluidCascade {
159
159
  * @param {import("../../../engine/graphics/render/frame_graph/FramePassResources.js").FramePassResources} resources
160
160
  * @param {{encoder: ShadeGPUCommandContext}} context
161
161
  */
162
- static "__#281@#execute"(record: object, resources: import("../../../engine/graphics/render/frame_graph/FramePassResources.js").FramePassResources, context: {
162
+ static "__#283@#execute"(record: object, resources: import("../../../engine/graphics/render/frame_graph/FramePassResources.js").FramePassResources, context: {
163
163
  encoder: ShadeGPUCommandContext;
164
164
  }): void;
165
165
  /**
@@ -63,7 +63,7 @@ export class GPUFluidCascadeStack {
63
63
  * @param {*} _resources
64
64
  * @param {{encoder: import("../../device/ShadeGPUCommandContext.js").ShadeGPUCommandContext}} context
65
65
  */
66
- static "__#283@#execute_publish"(pass: object, _resources: any, context: {
66
+ static "__#285@#execute_publish"(pass: object, _resources: any, context: {
67
67
  encoder: import("../../device/ShadeGPUCommandContext.js").ShadeGPUCommandContext;
68
68
  }): void;
69
69
  /**
@@ -90,19 +90,19 @@ export class GPUFluidForcing {
90
90
  * @param {number} clear_size bytes cleared from 0 when the pool reuses the buffer
91
91
  * @returns {BufferResourceDescriptor}
92
92
  */
93
- static "__#284@#descriptor"(kept: BufferResourceDescriptor[], role: number, size: number, usage: number, clear_size: number): BufferResourceDescriptor;
93
+ static "__#286@#descriptor"(kept: BufferResourceDescriptor[], role: number, size: number, usage: number, clear_size: number): BufferResourceDescriptor;
94
94
  /**
95
95
  * @param {object} record
96
96
  * @param {FramePassResources} resources
97
97
  * @param {{encoder: ShadeGPUCommandContext}} context
98
98
  */
99
- static "__#284@#execute_extract"(record: object, resources: FramePassResources, context: {
99
+ static "__#286@#execute_extract"(record: object, resources: FramePassResources, context: {
100
100
  encoder: ShadeGPUCommandContext;
101
101
  }): void;
102
- static "__#284@#execute_clear"(record: any, _resources: any, context: any): void;
103
- static "__#284@#execute_query"(record: any, resources: any, context: any): void;
104
- static "__#284@#execute_command"(record: any, resources: any, context: any): void;
105
- static "__#284@#execute_apply"(record: any, resources: any, context: any): void;
102
+ static "__#286@#execute_clear"(record: any, _resources: any, context: any): void;
103
+ static "__#286@#execute_query"(record: any, resources: any, context: any): void;
104
+ static "__#286@#execute_command"(record: any, resources: any, context: any): void;
105
+ static "__#286@#execute_apply"(record: any, resources: any, context: any): void;
106
106
  /**
107
107
  * @param {object} options
108
108
  * @param {GPUDevice} options.device
@@ -41,7 +41,7 @@ export class GPUFluidPressureSolve {
41
41
  * @param {*} _resources
42
42
  * @param {{encoder: ShadeGPUCommandContext}} context
43
43
  */
44
- static "__#280@#execute"(data: {
44
+ static "__#282@#execute"(data: {
45
45
  solve: GPUFluidPressureSolve;
46
46
  arm: number;
47
47
  count: number;
@@ -49,7 +49,7 @@ export class GPUFluidQueries {
49
49
  * @param {import("../../../../engine/graphics/render/frame_graph/FramePassResources.js").FramePassResources} resources
50
50
  * @param {{encoder: import("../../../device/ShadeGPUCommandContext.js").ShadeGPUCommandContext}} context
51
51
  */
52
- static "__#285@#execute"(pass: object, resources: import("../../../../engine/graphics/render/frame_graph/FramePassResources.js").FramePassResources, context: {
52
+ static "__#287@#execute"(pass: object, resources: import("../../../../engine/graphics/render/frame_graph/FramePassResources.js").FramePassResources, context: {
53
53
  encoder: import("../../../device/ShadeGPUCommandContext.js").ShadeGPUCommandContext;
54
54
  }): void;
55
55
  /**
@@ -33,7 +33,7 @@ export class GPUProbeClipmapGI {
33
33
  * @param {ProbeClipmapSettings} settings
34
34
  * @returns {boolean} whether it is what the settings' world cache describes, in their frustum's windows
35
35
  */
36
- static "__#206@#world_cache_built_for"(world_cache: GPUProbeClipmap, settings: ProbeClipmapSettings): boolean;
36
+ static "__#208@#world_cache_built_for"(world_cache: GPUProbeClipmap, settings: ProbeClipmapSettings): boolean;
37
37
  /**
38
38
  * @param {GraphicsContext} graphics
39
39
  */
@@ -72,13 +72,15 @@ export class GPULightCollection {
72
72
  */
73
73
  update(ctx: GraphicsContext): void;
74
74
  /**
75
- * Hold a `transforms` row for every light's entity, and let go of the rows of lights that left.
75
+ * Hold a `transforms` row for every light's entity.
76
76
  *
77
77
  * Called by the scene context before it flushes its rows, so a light that arrived this frame is
78
78
  * written this frame; runs only when the source's version moved, and a moved light is one of
79
79
  * the things that moves it, so every held row is marked as well — a mark on a row the GPU
80
80
  * composes writes nothing.
81
81
  *
82
+ * The row of a light that leaves goes as it leaves ({@link #removed}), not here.
83
+ *
82
84
  * @param {import("../scene/rows/GPUSceneRows.js").GPUSceneRows} rows
83
85
  */
84
86
  sync_rows(rows: import("../scene/rows/GPUSceneRows.js").GPUSceneRows): void;
@@ -1 +1 @@
1
- {"version":3,"file":"GPULightCollection.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/light/GPULightCollection.js"],"names":[],"mappings":"AAoDA;IAEI;;;;;OAKG;IACH,iCAFW,eAAe,QAOzB;IA6KD;;;;;;OAMG;IACH,sBALW,eAAe,aACf,eAAe,EA2CzB;IAnND;;;OAGG;IACH,6DAEC;IAeD;;OAEG;IACH,4BAEC;IAED;;;;;;OAMG;IACH,6BAEC;IAED;;;;;;;OAOG;IACH,qFAEC;IAWD;;OAEG;IACH,+CAEC;IA6DD;;;OAGG;IACH,qCAEC;IAED;;;;;;OAMG;IACH,gCAEC;IAED;;;;;;OAMG;IACH,yCAEC;IAGD,4BAMC;IAoMD;;;OAGG;IACH,YAFW,eAAe,QAoCzB;IAED;;;;;;;;;OASG;IACH,gBAFW,OAAO,+BAA+B,EAAE,YAAY,QAkC9D;IAED;;;;;;OAMG;IACH,uBAHW,sBAAsB,mCA6BhC;IAwED,gBAUC;;CACJ;8BA1lBY,OAAO,0CAA0C,EAAE,eAAe;8BAClE,OAAO,uBAAuB,EAAE,eAAe;8BAC/C,OAAO,6BAA6B,EAAE,eAAe;8BACrD,OAAO,sBAAsB,EAAE,eAAe;4BA7B/B,gCAAgC;yCACnB,2CAA2C;kCAClD,iCAAiC;uCAH5B,wCAAwC"}
1
+ {"version":3,"file":"GPULightCollection.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/light/GPULightCollection.js"],"names":[],"mappings":"AAoDA;IAEI;;;;;OAKG;IACH,iCAFW,eAAe,QAOzB;IAmLD;;;;;;OAMG;IACH,sBALW,eAAe,aACf,eAAe,EA6CzB;IA3ND;;;OAGG;IACH,6DAEC;IAeD;;OAEG;IACH,4BAEC;IAED;;;;;;OAMG;IACH,6BAEC;IAED;;;;;;;OAOG;IACH,qFAEC;IAWD;;OAEG;IACH,+CAEC;IAmED;;;OAGG;IACH,qCAEC;IAED;;;;;;OAMG;IACH,gCAEC;IAED;;;;;;OAMG;IACH,yCAEC;IAGD,4BAMC;IAsMD;;;OAGG;IACH,YAFW,eAAe,QAoCzB;IAED;;;;;;;;;;;OAWG;IACH,gBAFW,OAAO,+BAA+B,EAAE,YAAY,QA2B9D;IAqBD;;;;;;OAMG;IACH,uBAHW,sBAAsB,mCA6BhC;IAwED,gBAaC;;CACJ;8BAnnBY,OAAO,0CAA0C,EAAE,eAAe;8BAClE,OAAO,uBAAuB,EAAE,eAAe;8BAC/C,OAAO,6BAA6B,EAAE,eAAe;8BACrD,OAAO,sBAAsB,EAAE,eAAe;4BA7B/B,gCAAgC;yCACnB,2CAA2C;kCAClD,iCAAiC;uCAH5B,wCAAwC"}
@@ -150,6 +150,12 @@ export class GPULightCollection {
150
150
  */
151
151
  #held = new Map();
152
152
 
153
+ /**
154
+ * The rows {@link #held} is held in: the scene context's, from the first {@link sync_rows}.
155
+ * @type {import("../scene/rows/GPUSceneRows.js").GPUSceneRows|null}
156
+ */
157
+ #rows = null;
158
+
153
159
  /**
154
160
  * The source version {@link sync_rows} last reconciled the held rows against.
155
161
  * @type {number}
@@ -254,6 +260,8 @@ export class GPULightCollection {
254
260
  this.#device = device;
255
261
  this.#source = scene.lights;
256
262
 
263
+ this.#source.onRemoved.add(this.#removed, this);
264
+
257
265
  this.#environment = new GPUTextureContext(this.#device);
258
266
  this.#environment.descriptor.label = "environment map";
259
267
  this.#environment.descriptor.format = "rgba16float";
@@ -471,13 +479,15 @@ export class GPULightCollection {
471
479
  }
472
480
 
473
481
  /**
474
- * Hold a `transforms` row for every light's entity, and let go of the rows of lights that left.
482
+ * Hold a `transforms` row for every light's entity.
475
483
  *
476
484
  * Called by the scene context before it flushes its rows, so a light that arrived this frame is
477
485
  * written this frame; runs only when the source's version moved, and a moved light is one of
478
486
  * the things that moves it, so every held row is marked as well — a mark on a row the GPU
479
487
  * composes writes nothing.
480
488
  *
489
+ * The row of a light that leaves goes as it leaves ({@link #removed}), not here.
490
+ *
481
491
  * @param {import("../scene/rows/GPUSceneRows.js").GPUSceneRows} rows
482
492
  */
483
493
  sync_rows(rows) {
@@ -487,6 +497,8 @@ export class GPULightCollection {
487
497
  return;
488
498
  }
489
499
 
500
+ this.#rows = rows;
501
+
490
502
  const held = this.#held;
491
503
  const lights = source.elements;
492
504
 
@@ -502,16 +514,26 @@ export class GPULightCollection {
502
514
  }
503
515
  }
504
516
 
505
- if (held.size !== lights.length) {
506
- for (const [light, entity] of held) {
507
- if (!source.has(light)) {
508
- rows.release(entity);
509
- held.delete(light);
510
- }
511
- }
517
+ this.#rows_version = source.version;
518
+ }
519
+
520
+ /**
521
+ * A light left the scene's collection: its row goes now, while its entity is still the one
522
+ * that id names.
523
+ *
524
+ * @param {import("./model/Light.js").Light} light
525
+ */
526
+ #removed(light) {
527
+ const entity = this.#held.get(light);
528
+
529
+ if (entity === undefined) {
530
+ // not taken yet — it arrived and left between two builds
531
+ return;
512
532
  }
513
533
 
514
- this.#rows_version = source.version;
534
+ this.#held.delete(light);
535
+
536
+ this.#rows.release(entity);
515
537
  }
516
538
 
517
539
  /**
@@ -620,8 +642,11 @@ export class GPULightCollection {
620
642
  }
621
643
 
622
644
  destroy() {
645
+ this.#source.onRemoved.remove(this.#removed, this);
646
+
623
647
  // the rows go with the context that held them
624
648
  this.#held.clear();
649
+ this.#rows = null;
625
650
  this.#rows_version = -1;
626
651
 
627
652
  this.#shadow_context.destroy();
@@ -7,9 +7,11 @@
7
7
  *
8
8
  * A light is placed by naming the entity it stands at: the entity's `transforms` row is where the
9
9
  * GPU reads the light's pose from, and the scene's GPU context holds that row on the collection's
10
- * behalf for as long as the light is here. The collection itself is CPU data — the renderer's
11
- * mirror of it (`GPULightCollection`) is rebuilt whenever {@link version} moves, which adding and
12
- * removing do on their own and a change in place does through {@link needsUpdate}.
10
+ * behalf for as long as the light is here: taken by the next build, let go as the light leaves
11
+ * ({@link onRemoved}), since the entity may go next and its id be handed on. The collection itself
12
+ * is CPU data — the renderer's mirror of it (`GPULightCollection`) is rebuilt whenever
13
+ * {@link version} moves, which adding and removing do on their own and a change in place does
14
+ * through {@link needsUpdate}.
13
15
  */
14
16
  export class LightCollection {
15
17
  /**
@@ -49,6 +51,14 @@ export class LightCollection {
49
51
  * @param {number} entity
50
52
  */
51
53
  add(light: Light, entity: number): void;
54
+ /**
55
+ * A light has left, and the entity it stood at with it — sent from {@link remove}, before the
56
+ * caller can remove that entity and its dataset hand the id to another. Whatever holds the
57
+ * entity's row for the light lets go here.
58
+ *
59
+ * @type {Signal<Light, number>} the light, its entity
60
+ */
61
+ onRemoved: any;
52
62
  /**
53
63
  * Remove a light. Returns true if it was found and dropped.
54
64
  *