@woosh/meep-engine 3.60.8 → 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 (124) 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/shade/renderer/GraphicsContext.d.ts +8 -0
  39. package/src/shade/renderer/GraphicsContext.d.ts.map +1 -1
  40. package/src/shade/renderer/GraphicsContext.js +29 -0
  41. package/src/shade/renderer/Renderer.d.ts +10 -0
  42. package/src/shade/renderer/Renderer.d.ts.map +1 -1
  43. package/src/shade/renderer/Renderer.js +22 -2
  44. package/src/shade/renderer/fluid/GPUFluidCascade.d.ts +3 -3
  45. package/src/shade/renderer/fluid/GPUFluidCascadeStack.d.ts +1 -1
  46. package/src/shade/renderer/fluid/forcing/GPUFluidForcing.d.ts +6 -6
  47. package/src/shade/renderer/fluid/pressure/GPUFluidPressureSolve.d.ts +1 -1
  48. package/src/shade/renderer/fluid/query/GPUFluidQueries.d.ts +1 -1
  49. package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.d.ts +1 -1
  50. package/src/shade/renderer/light/GPULightCollection.d.ts +3 -1
  51. package/src/shade/renderer/light/GPULightCollection.d.ts.map +1 -1
  52. package/src/shade/renderer/light/GPULightCollection.js +34 -9
  53. package/src/shade/renderer/light/LightCollection.d.ts +13 -3
  54. package/src/shade/renderer/light/LightCollection.d.ts.map +1 -1
  55. package/src/shade/renderer/light/LightCollection.js +19 -3
  56. package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +1 -1
  57. package/src/shade/renderer/material/GPUMaterialManager.d.ts +22 -0
  58. package/src/shade/renderer/material/GPUMaterialManager.d.ts.map +1 -1
  59. package/src/shade/renderer/material/GPUMaterialManager.js +30 -0
  60. package/src/shade/renderer/material/dispatch/GPUMaterialComputeDispatch.d.ts +75 -0
  61. package/src/shade/renderer/material/dispatch/GPUMaterialComputeDispatch.d.ts.map +1 -0
  62. package/src/shade/renderer/material/dispatch/GPUMaterialComputeDispatch.js +338 -0
  63. package/src/shade/renderer/material/dispatch/MATERIAL_DISPATCH_CONSTANTS.d.ts +50 -0
  64. package/src/shade/renderer/material/dispatch/MATERIAL_DISPATCH_CONSTANTS.d.ts.map +1 -0
  65. package/src/shade/renderer/material/dispatch/MATERIAL_DISPATCH_CONSTANTS.js +54 -0
  66. package/src/shade/renderer/material/dispatch/MaterialDispatch.d.ts +37 -0
  67. package/src/shade/renderer/material/dispatch/MaterialDispatch.d.ts.map +1 -0
  68. package/src/shade/renderer/material/dispatch/MaterialDispatch.js +31 -0
  69. package/src/shade/renderer/material/dispatch/MaterialDispatchRecords.d.ts +42 -0
  70. package/src/shade/renderer/material/dispatch/MaterialDispatchRecords.d.ts.map +1 -0
  71. package/src/shade/renderer/material/dispatch/MaterialDispatchRecords.js +132 -0
  72. package/src/shade/renderer/material/dispatch/chunk_material_mesh_key.d.ts +21 -0
  73. package/src/shade/renderer/material/dispatch/chunk_material_mesh_key.d.ts.map +1 -0
  74. package/src/shade/renderer/material/dispatch/chunk_material_mesh_key.js +46 -0
  75. package/src/shade/renderer/material/dispatch/chunk_material_quad_keys.d.ts +20 -0
  76. package/src/shade/renderer/material/dispatch/chunk_material_quad_keys.d.ts.map +1 -0
  77. package/src/shade/renderer/material/dispatch/chunk_material_quad_keys.js +111 -0
  78. package/src/shade/renderer/material/dispatch/chunk_material_quad_pack.d.ts +18 -0
  79. package/src/shade/renderer/material/dispatch/chunk_material_quad_pack.d.ts.map +1 -0
  80. package/src/shade/renderer/material/dispatch/chunk_material_quad_pack.js +33 -0
  81. package/src/shade/renderer/material/dispatch/gbuffer_compute.d.ts +116 -0
  82. package/src/shade/renderer/material/dispatch/gbuffer_compute.d.ts.map +1 -0
  83. package/src/shade/renderer/material/dispatch/gbuffer_compute.js +249 -0
  84. package/src/shade/renderer/material/dispatch/graph_material_dispatch_compute.d.ts +56 -0
  85. package/src/shade/renderer/material/dispatch/graph_material_dispatch_compute.d.ts.map +1 -0
  86. package/src/shade/renderer/material/dispatch/graph_material_dispatch_compute.js +315 -0
  87. package/src/shade/renderer/material/dispatch/shader_material_dispatch_commands.d.ts +16 -0
  88. package/src/shade/renderer/material/dispatch/shader_material_dispatch_commands.d.ts.map +1 -0
  89. package/src/shade/renderer/material/dispatch/shader_material_dispatch_commands.js +83 -0
  90. package/src/shade/renderer/material/dispatch/shader_material_pixel_count.d.ts +22 -0
  91. package/src/shade/renderer/material/dispatch/shader_material_pixel_count.d.ts.map +1 -0
  92. package/src/shade/renderer/material/dispatch/shader_material_pixel_count.js +133 -0
  93. package/src/shade/renderer/material/dispatch/shader_material_pixel_scatter.d.ts +14 -0
  94. package/src/shade/renderer/material/dispatch/shader_material_pixel_scatter.d.ts.map +1 -0
  95. package/src/shade/renderer/material/dispatch/shader_material_pixel_scatter.js +98 -0
  96. package/src/shade/renderer/material/standard/VT_MATERIAL_TEMPLATE.d.ts +1 -0
  97. package/src/shade/renderer/material/standard/VT_MATERIAL_TEMPLATE.d.ts.map +1 -1
  98. package/src/shade/renderer/material/standard/VT_MATERIAL_TEMPLATE.js +11 -0
  99. package/src/shade/renderer/material/standard/fragment_gbuffer.d.ts +41 -6
  100. package/src/shade/renderer/material/standard/fragment_gbuffer.d.ts.map +1 -1
  101. package/src/shade/renderer/material/standard/fragment_gbuffer.js +88 -29
  102. package/src/shade/renderer/material/template/ShadeMaterialTemplate.d.ts +13 -1
  103. package/src/shade/renderer/material/template/ShadeMaterialTemplate.d.ts.map +1 -1
  104. package/src/shade/renderer/material/template/ShadeMaterialTemplate.js +18 -1
  105. package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
  106. package/src/shade/renderer/scene/GPUSceneContext.d.ts +6 -0
  107. package/src/shade/renderer/scene/GPUSceneContext.d.ts.map +1 -1
  108. package/src/shade/renderer/scene/GPUSceneContext.js +17 -7
  109. package/src/shade/renderer/scene/Scene.d.ts +4 -3
  110. package/src/shade/renderer/scene/Scene.d.ts.map +1 -1
  111. package/src/shade/renderer/scene/Scene.js +54 -53
  112. package/src/shade/renderer/scene/rows/GPUSceneRows.d.ts +16 -0
  113. package/src/shade/renderer/scene/rows/GPUSceneRows.d.ts.map +1 -1
  114. package/src/shade/renderer/scene/rows/GPUSceneRows.js +34 -0
  115. package/src/shade/renderer/shader/chunk/geometry/normal/chunk_anti_alias_roughness_kaplanyan.d.ts +19 -0
  116. package/src/shade/renderer/shader/chunk/geometry/normal/chunk_anti_alias_roughness_kaplanyan.d.ts.map +1 -1
  117. package/src/shade/renderer/shader/chunk/geometry/normal/chunk_anti_alias_roughness_kaplanyan.js +55 -20
  118. package/src/shade/renderer/shader/chunk/subgroup/chunk_subgroup_keyed_append.d.ts +31 -0
  119. package/src/shade/renderer/shader/chunk/subgroup/chunk_subgroup_keyed_append.d.ts.map +1 -0
  120. package/src/shade/renderer/shader/chunk/subgroup/chunk_subgroup_keyed_append.js +77 -0
  121. package/src/shade/renderer/texture/virtual/VirtualTextureManager.d.ts +6 -0
  122. package/src/shade/renderer/texture/virtual/VirtualTextureManager.d.ts.map +1 -1
  123. package/src/shade/renderer/texture/virtual/VirtualTextureManager.js +15 -1
  124. package/src/shade/renderer/water/query/GPUWaterQueries.d.ts +1 -1
@@ -0,0 +1,31 @@
1
+ /**
2
+ * How the G-buffer pass runs each material's shader over that material's pixels of the visibility
3
+ * buffer. Both run the same laydown from the same shader body; they differ in what launches it.
4
+ *
5
+ * @readonly
6
+ * @enum {number}
7
+ */
8
+ export const MaterialDispatch = Object.freeze({
9
+ /**
10
+ * The default, and the main path. A fullscreen triangle per material, masked to the material's
11
+ * pixels by a depth-equal test against a material-id depth buffer written from the visibility
12
+ * buffer first — the material-depth trick of [Doghramachi17], and Nanite's without compute
13
+ * materials. The rasterizer finds each material's pixels, once per material, over the whole
14
+ * screen.
15
+ */
16
+ Quad: 0,
17
+ /**
18
+ * **Experimental, off by default, not the main path.** It loses to {@link Quad} on high-end GPUs
19
+ * at every material count, because each material is its own dispatch; the measurements, and what
20
+ * would change that, are in `COMPUTE_MATERIAL_DISPATCH.md` beside this file.
21
+ *
22
+ * The visibility buffer is classified once into one list of 2×2 pixel quads per material,
23
+ * ordered by screen tile within each, and each material's shader then runs in compute over its
24
+ * own list, one indirect dispatch per material — the "material compute dispatch" of DOOM: The
25
+ * Dark Ages (Lazarek & Hammer, GPC 2025, after [McLaren22]). No pixel of another material is
26
+ * visited, except a quad's others, which run as a fragment quad's helper lanes would so that the
27
+ * laydown's one screen-space derivative, the specular anti-aliasing footprint, is the fragment
28
+ * path's.
29
+ */
30
+ Compute: 1,
31
+ });
@@ -0,0 +1,42 @@
1
+ /**
2
+ * @typedef {import("../../binding/BindGroupManager.js").BindGroupManager} BindGroupManager
3
+ */
4
+ /**
5
+ * Where the compute material dispatch keeps its per-material records: one
6
+ * {@link MATERIAL_DISPATCH_RECORD_STRUCT} every {@link MATERIAL_DISPATCH_RECORD_STRIDE} bytes, which
7
+ * the GPU writes each frame and each material's dispatch then reads twice — as its indirect command,
8
+ * and as its group 3 — and the bind group over each material's slice.
9
+ *
10
+ * Kept across frames, so the bind groups are made once per slot rather than once per frame. Grows to
11
+ * the longest material list it is asked for and stays there; a record is 256 bytes.
12
+ */
13
+ export class MaterialDispatchRecords {
14
+ /**
15
+ * @param {GPUDevice} device
16
+ * @param {BindGroupManager} bindings
17
+ */
18
+ constructor(device: GPUDevice, bindings: BindGroupManager);
19
+ /**
20
+ * @returns {GPUBuffer|null}
21
+ */
22
+ get buffer(): any;
23
+ /**
24
+ * Make room for `slot_count` records. A larger buffer replaces the old one, which is destroyed,
25
+ * and the bind groups over it go with it — so reserve before a frame records anything that
26
+ * names the buffer, never between recording and executing it.
27
+ *
28
+ * @param {number} slot_count
29
+ */
30
+ reserve(slot_count: number): void;
31
+ /**
32
+ * The group 3 of `slot`'s dispatch: its own record, as a uniform.
33
+ *
34
+ * @param {number} slot below what {@link reserve} last made room for
35
+ * @returns {GPUBindGroup}
36
+ */
37
+ bind_group(slot: number): GPUBindGroup;
38
+ destroy(): void;
39
+ #private;
40
+ }
41
+ export type BindGroupManager = import("../../binding/BindGroupManager.js").BindGroupManager;
42
+ //# sourceMappingURL=MaterialDispatchRecords.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MaterialDispatchRecords.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/material/dispatch/MaterialDispatchRecords.js"],"names":[],"mappings":"AAKA;;GAEG;AAEH;;;;;;;;GAQG;AACH;IA4BI;;;OAGG;IACH,yCAFW,gBAAgB,EAK1B;IAED;;OAEG;IACH,kBAEC;IAED;;;;;;OAMG;IACH,oBAFW,MAAM,QA2BhB;IAED;;;;;OAKG;IACH,iBAHW,MAAM,gBAqBhB;IAED,gBAQC;;CACJ;+BA7HY,OAAO,mCAAmC,EAAE,gBAAgB"}
@@ -0,0 +1,132 @@
1
+ import { assert } from "../../../../core/assert.js";
2
+ import { BindGroupDescriptor } from "../../binding/BindGroupDescriptor.js";
3
+ import { GBUFFER_COMPUTE_DISPATCH_LAYOUT, MATERIAL_DISPATCH_RECORD_STRUCT } from "./gbuffer_compute.js";
4
+ import { MATERIAL_DISPATCH_RECORD_STRIDE } from "./MATERIAL_DISPATCH_CONSTANTS.js";
5
+
6
+ /**
7
+ * @typedef {import("../../binding/BindGroupManager.js").BindGroupManager} BindGroupManager
8
+ */
9
+
10
+ /**
11
+ * Where the compute material dispatch keeps its per-material records: one
12
+ * {@link MATERIAL_DISPATCH_RECORD_STRUCT} every {@link MATERIAL_DISPATCH_RECORD_STRIDE} bytes, which
13
+ * the GPU writes each frame and each material's dispatch then reads twice — as its indirect command,
14
+ * and as its group 3 — and the bind group over each material's slice.
15
+ *
16
+ * Kept across frames, so the bind groups are made once per slot rather than once per frame. Grows to
17
+ * the longest material list it is asked for and stays there; a record is 256 bytes.
18
+ */
19
+ export class MaterialDispatchRecords {
20
+ /**
21
+ * @type {GPUDevice}
22
+ */
23
+ #device;
24
+
25
+ /**
26
+ * @type {BindGroupManager}
27
+ */
28
+ #bindings;
29
+
30
+ /**
31
+ * @type {GPUBuffer|null}
32
+ */
33
+ #buffer = null;
34
+
35
+ /**
36
+ * Records the buffer holds.
37
+ * @type {number}
38
+ */
39
+ #capacity = 0;
40
+
41
+ /**
42
+ * By slot, made on first use over the current buffer.
43
+ * @type {GPUBindGroup[]}
44
+ */
45
+ #bind_groups = [];
46
+
47
+ /**
48
+ * @param {GPUDevice} device
49
+ * @param {BindGroupManager} bindings
50
+ */
51
+ constructor(device, bindings) {
52
+ this.#device = device;
53
+ this.#bindings = bindings;
54
+ }
55
+
56
+ /**
57
+ * @returns {GPUBuffer|null}
58
+ */
59
+ get buffer() {
60
+ return this.#buffer;
61
+ }
62
+
63
+ /**
64
+ * Make room for `slot_count` records. A larger buffer replaces the old one, which is destroyed,
65
+ * and the bind groups over it go with it — so reserve before a frame records anything that
66
+ * names the buffer, never between recording and executing it.
67
+ *
68
+ * @param {number} slot_count
69
+ */
70
+ reserve(slot_count) {
71
+ assert.isNonNegativeInteger(slot_count, 'slot_count');
72
+
73
+ if (slot_count <= this.#capacity) {
74
+ return;
75
+ }
76
+
77
+ let capacity = Math.max(1, this.#capacity);
78
+
79
+ while (capacity < slot_count) {
80
+ capacity *= 2;
81
+ }
82
+
83
+ if (this.#buffer !== null) {
84
+ this.#buffer.destroy();
85
+ }
86
+
87
+ this.#buffer = this.#device.createBuffer({
88
+ label: "Material dispatch records",
89
+ size: capacity * MATERIAL_DISPATCH_RECORD_STRIDE,
90
+ usage: GPUBufferUsage.STORAGE | GPUBufferUsage.INDIRECT | GPUBufferUsage.UNIFORM,
91
+ });
92
+
93
+ this.#capacity = capacity;
94
+ this.#bind_groups.length = 0;
95
+ }
96
+
97
+ /**
98
+ * The group 3 of `slot`'s dispatch: its own record, as a uniform.
99
+ *
100
+ * @param {number} slot below what {@link reserve} last made room for
101
+ * @returns {GPUBindGroup}
102
+ */
103
+ bind_group(slot) {
104
+ assert.lessThan(slot, this.#capacity, 'slot');
105
+
106
+ let group = this.#bind_groups[slot];
107
+
108
+ if (group === undefined) {
109
+ group = this.#bindings.create(BindGroupDescriptor.from(GBUFFER_COMPUTE_DISPATCH_LAYOUT, [
110
+ {
111
+ buffer: this.#buffer,
112
+ offset: slot * MATERIAL_DISPATCH_RECORD_STRIDE,
113
+ size: MATERIAL_DISPATCH_RECORD_STRUCT.size,
114
+ }
115
+ ]));
116
+
117
+ this.#bind_groups[slot] = group;
118
+ }
119
+
120
+ return group;
121
+ }
122
+
123
+ destroy() {
124
+ if (this.#buffer !== null) {
125
+ this.#buffer.destroy();
126
+ this.#buffer = null;
127
+ }
128
+
129
+ this.#capacity = 0;
130
+ this.#bind_groups.length = 0;
131
+ }
132
+ }
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Which (material, tile) list a mesh of the visibility buffer puts its pixels of `tile` in:
3
+ *
4
+ * ```wgsl
5
+ * fn material_mesh_key(mesh_index: u32, tile: u32, tile_count: u32) -> u32
6
+ * ```
7
+ *
8
+ * `slot * tile_count + tile`, where `slot` is the mesh's material's place in the G-buffer pass's
9
+ * list, looked up by material id in `material_slots` (a {@link cpu_hash_table_create} table). So the
10
+ * keys run material by material, tile by tile within each.
11
+ *
12
+ * {@link SUBGROUP_KEYED_APPEND_NONE} where no G-buffer material draws the pixel: no mesh there, or
13
+ * one whose material the pass does not draw — a transparent one, or one without a context yet.
14
+ *
15
+ * Reads `scene_database` and `material_slots`.
16
+ *
17
+ * @type {CodeChunk}
18
+ */
19
+ export const chunk_material_mesh_key: CodeChunk;
20
+ import { CodeChunk } from "../../shader/compiler/CodeChunk.js";
21
+ //# sourceMappingURL=chunk_material_mesh_key.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunk_material_mesh_key.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/material/dispatch/chunk_material_mesh_key.js"],"names":[],"mappings":"AAMA;;;;;;;;;;;;;;;;;GAiBG;AACH,sCAFU,SAAS,CAuBhB;0BA1CuB,oCAAoC"}
@@ -0,0 +1,46 @@
1
+ import { chunk_hash_table_get } from "../../gpu_primitive/hash_table/chunk_hash_table_get.js";
2
+ import { VIZ_BUFFER_INVALID_MESH_VALUE } from "../../rasterize/native/viz/VIZ_BUFFER_INVALID_MESH_VALUE.js";
3
+ import { chunk_scene_database_access } from "../../scene/chunk_scene_database_access.js";
4
+ import { CodeChunk } from "../../shader/compiler/CodeChunk.js";
5
+ import { SUBGROUP_KEYED_APPEND_NONE } from "../../shader/chunk/subgroup/chunk_subgroup_keyed_append.js";
6
+
7
+ /**
8
+ * Which (material, tile) list a mesh of the visibility buffer puts its pixels of `tile` in:
9
+ *
10
+ * ```wgsl
11
+ * fn material_mesh_key(mesh_index: u32, tile: u32, tile_count: u32) -> u32
12
+ * ```
13
+ *
14
+ * `slot * tile_count + tile`, where `slot` is the mesh's material's place in the G-buffer pass's
15
+ * list, looked up by material id in `material_slots` (a {@link cpu_hash_table_create} table). So the
16
+ * keys run material by material, tile by tile within each.
17
+ *
18
+ * {@link SUBGROUP_KEYED_APPEND_NONE} where no G-buffer material draws the pixel: no mesh there, or
19
+ * one whose material the pass does not draw — a transparent one, or one without a context yet.
20
+ *
21
+ * Reads `scene_database` and `material_slots`.
22
+ *
23
+ * @type {CodeChunk}
24
+ */
25
+ export const chunk_material_mesh_key = CodeChunk.from(
26
+ //language=WGSL
27
+ `
28
+ fn material_mesh_key(mesh_index: u32, tile: u32, tile_count: u32) -> u32 {
29
+ if (mesh_index == ${VIZ_BUFFER_INVALID_MESH_VALUE}u) {
30
+ return ${SUBGROUP_KEYED_APPEND_NONE}u;
31
+ }
32
+
33
+ let mesh = scene_read_mesh(&scene_database, mesh_index);
34
+
35
+ let slot = hash_table_get(&material_slots, 0u, mesh.material);
36
+
37
+ if (slot == 0xFFFFFFFFu) {
38
+ return ${SUBGROUP_KEYED_APPEND_NONE}u;
39
+ }
40
+
41
+ return slot * tile_count + tile;
42
+ }
43
+ `, [
44
+ chunk_hash_table_get,
45
+ chunk_scene_database_access,
46
+ ]);
@@ -0,0 +1,20 @@
1
+ /**
2
+ * The classification's read of one 2×2 quad of the visibility buffer.
3
+ *
4
+ * ```wgsl
5
+ * struct MaterialQuadKeys { keys: vec4<u32>, masks: vec4<u32> }
6
+ * fn material_quad_keys(quad: vec2<u32>, resolution: vec2<u32>, tiles_x: u32, tile_count: u32) -> MaterialQuadKeys
7
+ * ```
8
+ *
9
+ * `material_quad_keys` reads a quad of the visibility buffer and answers its distinct list keys —
10
+ * see {@link chunk_material_mesh_key} — in `keys.x` to `keys.w`, first to last in corner order, each
11
+ * with the mask of the corners it holds, as {@link chunk_material_quad_pack} packs it; past the last,
12
+ * {@link SUBGROUP_KEYED_APPEND_NONE} with an empty mask. A pixel outside `resolution`, or one that
13
+ * no material draws, is in no list and in no mask. A quad is in one tile, and its pixels are mostly
14
+ * one mesh, so a key is worked out once per distinct mesh.
15
+ *
16
+ * @type {CodeChunk}
17
+ */
18
+ export const chunk_material_quad_keys: CodeChunk;
19
+ import { CodeChunk } from "../../shader/compiler/CodeChunk.js";
20
+ //# sourceMappingURL=chunk_material_quad_keys.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunk_material_quad_keys.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/material/dispatch/chunk_material_quad_keys.js"],"names":[],"mappings":"AAMA;;;;;;;;;;;;;;;;GAgBG;AACH,uCAFU,SAAS,CAyFhB;0BA5GuB,oCAAoC"}
@@ -0,0 +1,111 @@
1
+ import { VIZ_BUFFER_INVALID_MESH_VALUE } from "../../rasterize/native/viz/VIZ_BUFFER_INVALID_MESH_VALUE.js";
2
+ import { SUBGROUP_KEYED_APPEND_NONE } from "../../shader/chunk/subgroup/chunk_subgroup_keyed_append.js";
3
+ import { CodeChunk } from "../../shader/compiler/CodeChunk.js";
4
+ import { chunk_material_mesh_key } from "./chunk_material_mesh_key.js";
5
+ import { MATERIAL_DISPATCH_TILE_SIZE } from "./MATERIAL_DISPATCH_CONSTANTS.js";
6
+
7
+ /**
8
+ * The classification's read of one 2×2 quad of the visibility buffer.
9
+ *
10
+ * ```wgsl
11
+ * struct MaterialQuadKeys { keys: vec4<u32>, masks: vec4<u32> }
12
+ * fn material_quad_keys(quad: vec2<u32>, resolution: vec2<u32>, tiles_x: u32, tile_count: u32) -> MaterialQuadKeys
13
+ * ```
14
+ *
15
+ * `material_quad_keys` reads a quad of the visibility buffer and answers its distinct list keys —
16
+ * see {@link chunk_material_mesh_key} — in `keys.x` to `keys.w`, first to last in corner order, each
17
+ * with the mask of the corners it holds, as {@link chunk_material_quad_pack} packs it; past the last,
18
+ * {@link SUBGROUP_KEYED_APPEND_NONE} with an empty mask. A pixel outside `resolution`, or one that
19
+ * no material draws, is in no list and in no mask. A quad is in one tile, and its pixels are mostly
20
+ * one mesh, so a key is worked out once per distinct mesh.
21
+ *
22
+ * @type {CodeChunk}
23
+ */
24
+ export const chunk_material_quad_keys = CodeChunk.from(
25
+ //language=WGSL
26
+ `
27
+ struct MaterialQuadKeys {
28
+ keys: vec4<u32>,
29
+ masks: vec4<u32>,
30
+ }
31
+
32
+ // the mesh at a corner, or none for a corner off the view
33
+ fn material_quad_mesh(quad: vec2<u32>, corner: vec2<u32>, resolution: vec2<u32>) -> u32 {
34
+ let pixel = quad * 2u + corner;
35
+
36
+ if (any(pixel >= resolution)) {
37
+ return ${VIZ_BUFFER_INVALID_MESH_VALUE}u;
38
+ }
39
+
40
+ return textureLoad(viz_buffer_mesh, vec2<i32>(pixel), 0).r;
41
+ }
42
+
43
+ // put a corner's key in its place among the distinct keys, written out rather than indexed: a
44
+ // vector indexed by a runtime value lives in local memory
45
+ fn material_quad_keys_add(s: ptr<function, MaterialQuadKeys>, key: u32, bit: u32) {
46
+ const NONE = ${SUBGROUP_KEYED_APPEND_NONE}u;
47
+
48
+ if (key == NONE) {
49
+ return;
50
+ }
51
+
52
+ if ((*s).keys.x == key || (*s).keys.x == NONE) {
53
+ (*s).keys.x = key;
54
+ (*s).masks.x |= bit;
55
+ } else if ((*s).keys.y == key || (*s).keys.y == NONE) {
56
+ (*s).keys.y = key;
57
+ (*s).masks.y |= bit;
58
+ } else if ((*s).keys.z == key || (*s).keys.z == NONE) {
59
+ (*s).keys.z = key;
60
+ (*s).masks.z |= bit;
61
+ } else {
62
+ (*s).keys.w = key;
63
+ (*s).masks.w |= bit;
64
+ }
65
+ }
66
+
67
+ fn material_quad_keys(quad: vec2<u32>, resolution: vec2<u32>, tiles_x: u32, tile_count: u32) -> MaterialQuadKeys {
68
+ let tile_xy = (quad * 2u) / ${MATERIAL_DISPATCH_TILE_SIZE}u;
69
+ let tile = tile_xy.x + tile_xy.y * tiles_x;
70
+
71
+ let m0 = material_quad_mesh(quad, vec2<u32>(0u, 0u), resolution);
72
+ let m1 = material_quad_mesh(quad, vec2<u32>(1u, 0u), resolution);
73
+ let m2 = material_quad_mesh(quad, vec2<u32>(0u, 1u), resolution);
74
+ let m3 = material_quad_mesh(quad, vec2<u32>(1u, 1u), resolution);
75
+
76
+ // one lookup per distinct mesh
77
+ let k0 = material_mesh_key(m0, tile, tile_count);
78
+
79
+ var k1 = k0;
80
+ if (m1 != m0) {
81
+ k1 = material_mesh_key(m1, tile, tile_count);
82
+ }
83
+
84
+ var k2 = k0;
85
+ if (m2 == m1) {
86
+ k2 = k1;
87
+ } else if (m2 != m0) {
88
+ k2 = material_mesh_key(m2, tile, tile_count);
89
+ }
90
+
91
+ var k3 = k0;
92
+ if (m3 == m2) {
93
+ k3 = k2;
94
+ } else if (m3 == m1) {
95
+ k3 = k1;
96
+ } else if (m3 != m0) {
97
+ k3 = material_mesh_key(m3, tile, tile_count);
98
+ }
99
+
100
+ var out = MaterialQuadKeys(vec4<u32>(${SUBGROUP_KEYED_APPEND_NONE}u), vec4<u32>(0u));
101
+
102
+ material_quad_keys_add(&out, k0, 1u);
103
+ material_quad_keys_add(&out, k1, 2u);
104
+ material_quad_keys_add(&out, k2, 4u);
105
+ material_quad_keys_add(&out, k3, 8u);
106
+
107
+ return out;
108
+ }
109
+ `, [
110
+ chunk_material_mesh_key,
111
+ ]);
@@ -0,0 +1,18 @@
1
+ /**
2
+ * An entry of a material's list: one 2×2 quad of pixels, and which of its four are the material's.
3
+ *
4
+ * ```wgsl
5
+ * struct MaterialQuad { quad: vec2<u32>, mask: u32 }
6
+ * fn material_quad_pack(quad: vec2<u32>, mask: u32) -> u32
7
+ * fn material_quad_unpack(word: u32) -> MaterialQuad
8
+ * ```
9
+ *
10
+ * A word holds the quad's column and row, 14 bits each — any texture a device can make — and the
11
+ * mask in the top 4, bit `corner` for the pixel at `corner`: 0 top left, 1 top right, 2 bottom
12
+ * left, 3 bottom right, which is how a quad of lanes is laid out for `quadBroadcast`.
13
+ *
14
+ * @type {CodeChunk}
15
+ */
16
+ export const chunk_material_quad_pack: CodeChunk;
17
+ import { CodeChunk } from "../../shader/compiler/CodeChunk.js";
18
+ //# sourceMappingURL=chunk_material_quad_pack.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunk_material_quad_pack.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/material/dispatch/chunk_material_quad_pack.js"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;GAcG;AACH,uCAFU,SAAS,CAiBhB;0BAhCuB,oCAAoC"}
@@ -0,0 +1,33 @@
1
+ import { CodeChunk } from "../../shader/compiler/CodeChunk.js";
2
+
3
+ /**
4
+ * An entry of a material's list: one 2×2 quad of pixels, and which of its four are the material's.
5
+ *
6
+ * ```wgsl
7
+ * struct MaterialQuad { quad: vec2<u32>, mask: u32 }
8
+ * fn material_quad_pack(quad: vec2<u32>, mask: u32) -> u32
9
+ * fn material_quad_unpack(word: u32) -> MaterialQuad
10
+ * ```
11
+ *
12
+ * A word holds the quad's column and row, 14 bits each — any texture a device can make — and the
13
+ * mask in the top 4, bit `corner` for the pixel at `corner`: 0 top left, 1 top right, 2 bottom
14
+ * left, 3 bottom right, which is how a quad of lanes is laid out for `quadBroadcast`.
15
+ *
16
+ * @type {CodeChunk}
17
+ */
18
+ export const chunk_material_quad_pack = CodeChunk.from(
19
+ //language=WGSL
20
+ `
21
+ struct MaterialQuad {
22
+ quad: vec2<u32>,
23
+ mask: u32,
24
+ }
25
+
26
+ fn material_quad_pack(quad: vec2<u32>, mask: u32) -> u32 {
27
+ return quad.x | (quad.y << 14u) | (mask << 28u);
28
+ }
29
+
30
+ fn material_quad_unpack(word: u32) -> MaterialQuad {
31
+ return MaterialQuad(vec2<u32>(word & 0x3FFFu, (word >> 14u) & 0x3FFFu), word >> 28u);
32
+ }
33
+ `);
@@ -0,0 +1,116 @@
1
+ /**
2
+ * The resource set of a compute G-buffer pipeline whose group 0 is `material_group`: the template's
3
+ * own group 0 and the fragment pipelines' group 2, which this code reads under the same names, and
4
+ * groups 1 and 3 of its own.
5
+ *
6
+ * @param {ShaderResourceGroupDescriptor} material_group
7
+ * @returns {ShaderResourceSetDescriptor}
8
+ */
9
+ export function build_gbuffer_compute_shader_resources(material_group: ShaderResourceGroupDescriptor): ShaderResourceSetDescriptor;
10
+ /**
11
+ * The compute entry of a template's G-buffer pipeline: a quad of lanes per 2×2 quad of pixels in
12
+ * the material's run of the list, {@link build_gbuffer_laydown} at each pixel's centre, and the
13
+ * result stored, for the pixels of the quad that are the material's, where the fragment dispatch's
14
+ * colour targets would have taken it.
15
+ *
16
+ * The quad's other pixels run the laydown as a fragment quad's helper lanes do, so the derivative
17
+ * the laydown takes is a fragment quad's — see {@link chunk_gbuffer_fwidth_quad}. So does the tail
18
+ * of the material's last workgroup, on its last quad again; every lane of a workgroup that holds any
19
+ * of the list runs the laydown, which keeps the quad operations in uniform control flow, and a
20
+ * workgroup wholly past the list leaves at once.
21
+ *
22
+ * Lanes take their places in subgroup order, through {@link chunk_subgroup_reserve_workgroup}, so a
23
+ * quad of places is a quad of lanes however subgroups are laid over the workgroup.
24
+ *
25
+ * Dispatched with a folded command — see {@link chunk_folded_workgroup_index} — so one material can
26
+ * cover more of the screen than one dispatch dimension reaches.
27
+ *
28
+ * @param {CodeChunk} surface defines `fn material_surface(s: MaterialSurfaceInput) -> MaterialSurfaceOutput`
29
+ * @returns {CodeChunk}
30
+ */
31
+ export function build_gbuffer_compute_body(surface: CodeChunk): CodeChunk;
32
+ /**
33
+ * The compute G-buffer pipeline of a template: its group 0 and surface function around the shared
34
+ * laydown. Every group is laid out for the compute stage, whatever stages its declaration names, so
35
+ * no template has to declare anything for this pipeline: a material's group 0 for it is a bind group
36
+ * of its own, made by the template's own hook over this layout.
37
+ *
38
+ * @param {Object} options
39
+ * @param {string} options.label
40
+ * @param {ShaderResourceGroupDescriptor} options.material_group the template's group 0
41
+ * @param {CodeChunk} options.surface defines `material_surface`
42
+ * @returns {ComputePipelineDescriptor}
43
+ */
44
+ export function build_gbuffer_compute_pipeline_descriptor({ label, material_group, surface }: {
45
+ label: string;
46
+ material_group: ShaderResourceGroupDescriptor;
47
+ surface: CodeChunk;
48
+ }): ComputePipelineDescriptor;
49
+ /**
50
+ * What one material's compute dispatch is for: its indirect workgroup counts, which the dispatch is
51
+ * issued with, and the run of the pixel list it shades. Written by
52
+ * {@link shader_material_dispatch_commands}, one per material at
53
+ * {@link MATERIAL_DISPATCH_RECORD_STRIDE}, and bound to the dispatch as its own uniform.
54
+ *
55
+ * @type {WebGPUStruct}
56
+ */
57
+ export const MATERIAL_DISPATCH_RECORD_STRUCT: WebGPUStruct;
58
+ /**
59
+ * @typedef {import("../../../descriptor/binding/BindGroupLayoutDescriptor.js").BindGroupLayoutDescriptor} BindGroupLayoutDescriptor
60
+ */
61
+ /**
62
+ * Group 1 of every template's compute G-buffer pipeline: what {@link build_gbuffer_laydown} reads
63
+ * of the visibility buffer and the view, under the names the laydown reads them by, then the quad
64
+ * lists the dispatch walks and the G-buffer it writes.
65
+ *
66
+ * One bind group a frame serves every template.
67
+ *
68
+ * @type {ShaderResourceGroupDescriptor}
69
+ */
70
+ export const g_buffer_viz_compute_resources: ShaderResourceGroupDescriptor;
71
+ /**
72
+ * Group 3 of every template's compute G-buffer pipeline: the dispatch's own record. A bind group
73
+ * per material, over that material's slice of the record buffer, so the shader learns which run of
74
+ * the pixel list is its own from the one thing that differs between the dispatches.
75
+ *
76
+ * @type {ShaderResourceGroupDescriptor}
77
+ */
78
+ export const g_buffer_dispatch_resources: ShaderResourceGroupDescriptor;
79
+ /**
80
+ * Group 1 as every compute G-buffer pipeline lays it out.
81
+ *
82
+ * @type {BindGroupLayoutDescriptor}
83
+ */
84
+ export const GBUFFER_COMPUTE_VIZ_LAYOUT: BindGroupLayoutDescriptor;
85
+ /**
86
+ * Group 2 as every compute G-buffer pipeline lays it out: the fragment pipelines' scene group,
87
+ * visible to compute.
88
+ *
89
+ * @type {BindGroupLayoutDescriptor}
90
+ */
91
+ export const GBUFFER_COMPUTE_SCENE_LAYOUT: BindGroupLayoutDescriptor;
92
+ /**
93
+ * Group 3 as every compute G-buffer pipeline lays it out.
94
+ *
95
+ * @type {BindGroupLayoutDescriptor}
96
+ */
97
+ export const GBUFFER_COMPUTE_DISPATCH_LAYOUT: BindGroupLayoutDescriptor;
98
+ /**
99
+ * `fn gbuffer_fwidth(v: vec2<f32>) -> vec2<f32>` for {@link build_gbuffer_laydown} in the compute
100
+ * material dispatch, whose quad of lanes is a 2×2 quad of pixels: `fwidth` taken coarse, across the
101
+ * quad's top row and left column. That is what a fragment's `fwidth` is on D3D12; WGSL lets a backend
102
+ * take it fine instead, and there the two paths' filtered roughness differs where the normal varies
103
+ * between a quad's rows.
104
+ *
105
+ * Called from uniform control flow, with every lane of the quad running the laydown.
106
+ *
107
+ * @type {CodeChunk}
108
+ */
109
+ export const chunk_gbuffer_fwidth_quad: CodeChunk;
110
+ export type BindGroupLayoutDescriptor = import("../../../descriptor/binding/BindGroupLayoutDescriptor.js").BindGroupLayoutDescriptor;
111
+ import { ShaderResourceGroupDescriptor } from "../../shader/resource/ShaderResourceGroupDescriptor.js";
112
+ import { ShaderResourceSetDescriptor } from "../../shader/resource/ShaderResourceSetDescriptor.js";
113
+ import { CodeChunk } from "../../shader/compiler/CodeChunk.js";
114
+ import { ComputePipelineDescriptor } from "../../../descriptor/pipeline/compute/ComputePipelineDescriptor.js";
115
+ import { WebGPUStruct } from "../../shader/type/WebGPUStruct.js";
116
+ //# sourceMappingURL=gbuffer_compute.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gbuffer_compute.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/material/dispatch/gbuffer_compute.js"],"names":[],"mappings":"AA6GA;;;;;;;GAOG;AACH,uEAHW,6BAA6B,GAC3B,2BAA2B,CAWvC;AA0BD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,oDAHW,SAAS,GACP,SAAS,CAgDrB;AAED;;;;;;;;;;;GAWG;AACH;IAL2B,KAAK,EAArB,MAAM;IACiC,cAAc,EAArD,6BAA6B;IACV,OAAO,EAA1B,SAAS;IACP,yBAAyB,CAiBrC;AAlOD;;;;;;;GAOG;AACH,8CAFU,YAAY,CAcO;AAE7B;;GAEG;AAEH;;;;;;;;GAQG;AACH,6CAFU,6BAA6B,CAE2C;AAelF;;;;;;GAMG;AACH,0CAFU,6BAA6B,CAEwC;AAQ/E;;;;GAIG;AACH,yCAFU,yBAAyB,CAEgG;AAEnI;;;;;GAKG;AACH,2CAFU,yBAAyB,CAE4F;AAE/H;;;;GAIG;AACH,8CAFU,yBAAyB,CAEkG;AAqBrI;;;;;;;;;;GAUG;AACH,wCAFU,SAAS,CAWhB;wCAvGU,OAAO,0DAA0D,EAAE,yBAAyB;8CArC3D,wDAAwD;4CAC1D,sDAAsD;0BAFxE,oCAAoC;0CANpB,mEAAmE;6BAYhF,mCAAmC"}