@woosh/meep-engine 3.10.0 → 3.11.1

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 (164) hide show
  1. package/README.md +168 -152
  2. package/package.json +1 -1
  3. package/src/REVIEW_2026_08_06.md +610 -610
  4. package/src/core/geom/3d/shape/ConvexHullShape3D.d.ts.map +1 -1
  5. package/src/core/geom/3d/shape/ConvexHullShape3D.js +28 -4
  6. package/src/engine/graphics/render/frame_graph/FrameGraph.d.ts +26 -0
  7. package/src/engine/graphics/render/frame_graph/FrameGraph.d.ts.map +1 -1
  8. package/src/engine/graphics/render/frame_graph/FrameGraph.js +47 -0
  9. package/src/engine/physics/ecs/PhysicsSystem.d.ts +0 -3
  10. package/src/engine/physics/ecs/PhysicsSystem.d.ts.map +1 -1
  11. package/src/engine/physics/ecs/PhysicsSystem.js +0 -3
  12. package/src/shade/device/ShadeGPUCommandContext.d.ts +21 -0
  13. package/src/shade/device/ShadeGPUCommandContext.d.ts.map +1 -1
  14. package/src/shade/device/ShadeGPUCommandContext.js +940 -749
  15. package/src/shade/device/timing/GPUTimerArray.d.ts +22 -4
  16. package/src/shade/device/timing/GPUTimerArray.d.ts.map +1 -1
  17. package/src/shade/device/timing/GPUTimerArray.js +88 -14
  18. package/src/shade/device/timing/GPU_PROFILER_PROPOSAL_2026_08_28.md +349 -98
  19. package/src/shade/device/timing/profile/GPUFrameRecorder.d.ts +93 -0
  20. package/src/shade/device/timing/profile/GPUFrameRecorder.d.ts.map +1 -0
  21. package/src/shade/device/timing/profile/GPUFrameRecorder.js +297 -0
  22. package/src/shade/device/timing/profile/GPUProfileCapture.d.ts +62 -0
  23. package/src/shade/device/timing/profile/GPUProfileCapture.d.ts.map +1 -0
  24. package/src/shade/device/timing/profile/GPUProfileCapture.js +77 -0
  25. package/src/shade/device/timing/profile/GPUProfileFrame.d.ts +73 -0
  26. package/src/shade/device/timing/profile/GPUProfileFrame.d.ts.map +1 -0
  27. package/src/shade/device/timing/profile/GPUProfileFrame.js +88 -0
  28. package/src/shade/device/timing/profile/GPUProfileLevel.d.ts +20 -0
  29. package/src/shade/device/timing/profile/GPUProfileLevel.d.ts.map +1 -0
  30. package/src/shade/device/timing/profile/GPUProfileLevel.js +50 -0
  31. package/src/shade/device/timing/profile/GPUProfileMeta.d.ts +63 -0
  32. package/src/shade/device/timing/profile/GPUProfileMeta.d.ts.map +1 -0
  33. package/src/shade/device/timing/profile/GPUProfileMeta.js +73 -0
  34. package/src/shade/device/timing/profile/GPUProfileSession.d.ts +173 -0
  35. package/src/shade/device/timing/profile/GPUProfileSession.d.ts.map +1 -0
  36. package/src/shade/device/timing/profile/GPUProfileSession.js +470 -0
  37. package/src/shade/device/timing/profile/GPUProfileSpan.d.ts +60 -0
  38. package/src/shade/device/timing/profile/GPUProfileSpan.d.ts.map +1 -0
  39. package/src/shade/device/timing/profile/GPUProfileSpan.js +65 -0
  40. package/src/shade/device/timing/profile/GPUProfileSpanKind.d.ts +19 -0
  41. package/src/shade/device/timing/profile/GPUProfileSpanKind.d.ts.map +1 -0
  42. package/src/shade/device/timing/profile/GPUProfileSpanKind.js +25 -0
  43. package/src/shade/device/timing/profile/GPUProfileTopology.d.ts +159 -0
  44. package/src/shade/device/timing/profile/GPUProfileTopology.d.ts.map +1 -0
  45. package/src/shade/device/timing/profile/GPUProfileTopology.js +202 -0
  46. package/src/shade/device/timing/profile/GPUProfileWork.d.ts +90 -0
  47. package/src/shade/device/timing/profile/GPUProfileWork.d.ts.map +1 -0
  48. package/src/shade/device/timing/profile/GPUProfileWork.js +115 -0
  49. package/src/shade/device/timing/profile/SGPTDefect.d.ts +43 -0
  50. package/src/shade/device/timing/profile/SGPTDefect.d.ts.map +1 -0
  51. package/src/shade/device/timing/profile/SGPTDefect.js +65 -0
  52. package/src/shade/device/timing/profile/SGPTHeader.d.ts +38 -0
  53. package/src/shade/device/timing/profile/SGPTHeader.d.ts.map +1 -0
  54. package/src/shade/device/timing/profile/SGPTHeader.js +46 -0
  55. package/src/shade/device/timing/profile/SGPTRecordRef.d.ts +37 -0
  56. package/src/shade/device/timing/profile/SGPTRecordRef.d.ts.map +1 -0
  57. package/src/shade/device/timing/profile/SGPTRecordRef.js +45 -0
  58. package/src/shade/device/timing/profile/SGPTWriteStream.d.ts +103 -0
  59. package/src/shade/device/timing/profile/SGPTWriteStream.d.ts.map +1 -0
  60. package/src/shade/device/timing/profile/SGPTWriteStream.js +287 -0
  61. package/src/shade/device/timing/profile/SGPT_DEFECT.d.ts +19 -0
  62. package/src/shade/device/timing/profile/SGPT_DEFECT.d.ts.map +1 -0
  63. package/src/shade/device/timing/profile/SGPT_DEFECT.js +26 -0
  64. package/src/shade/device/timing/profile/SGPT_FLAG.d.ts +8 -0
  65. package/src/shade/device/timing/profile/SGPT_FLAG.d.ts.map +1 -0
  66. package/src/shade/device/timing/profile/SGPT_FLAG.js +15 -0
  67. package/src/shade/device/timing/profile/SGPT_FORMAT.md +345 -0
  68. package/src/shade/device/timing/profile/SGPT_FORMAT_VERSION.d.ts +10 -0
  69. package/src/shade/device/timing/profile/SGPT_FORMAT_VERSION.d.ts.map +1 -0
  70. package/src/shade/device/timing/profile/SGPT_FORMAT_VERSION.js +9 -0
  71. package/src/shade/device/timing/profile/SGPT_FRAME_SLACK.d.ts +17 -0
  72. package/src/shade/device/timing/profile/SGPT_FRAME_SLACK.d.ts.map +1 -0
  73. package/src/shade/device/timing/profile/SGPT_FRAME_SLACK.js +16 -0
  74. package/src/shade/device/timing/profile/SGPT_HEADER_CHECKSUM_COVERAGE.d.ts +16 -0
  75. package/src/shade/device/timing/profile/SGPT_HEADER_CHECKSUM_COVERAGE.d.ts.map +1 -0
  76. package/src/shade/device/timing/profile/SGPT_HEADER_CHECKSUM_COVERAGE.js +15 -0
  77. package/src/shade/device/timing/profile/SGPT_HEADER_OFFSET.d.ts +15 -0
  78. package/src/shade/device/timing/profile/SGPT_HEADER_OFFSET.d.ts.map +1 -0
  79. package/src/shade/device/timing/profile/SGPT_HEADER_OFFSET.js +29 -0
  80. package/src/shade/device/timing/profile/SGPT_HEADER_SIZE.d.ts +7 -0
  81. package/src/shade/device/timing/profile/SGPT_HEADER_SIZE.d.ts.map +1 -0
  82. package/src/shade/device/timing/profile/SGPT_HEADER_SIZE.js +6 -0
  83. package/src/shade/device/timing/profile/SGPT_MAGIC.d.ts +7 -0
  84. package/src/shade/device/timing/profile/SGPT_MAGIC.d.ts.map +1 -0
  85. package/src/shade/device/timing/profile/SGPT_MAGIC.js +6 -0
  86. package/src/shade/device/timing/profile/SGPT_MIN_READER_VERSION.d.ts +16 -0
  87. package/src/shade/device/timing/profile/SGPT_MIN_READER_VERSION.d.ts.map +1 -0
  88. package/src/shade/device/timing/profile/SGPT_MIN_READER_VERSION.js +15 -0
  89. package/src/shade/device/timing/profile/SGPT_RECORD_HEADER_SIZE.d.ts +7 -0
  90. package/src/shade/device/timing/profile/SGPT_RECORD_HEADER_SIZE.d.ts.map +1 -0
  91. package/src/shade/device/timing/profile/SGPT_RECORD_HEADER_SIZE.js +6 -0
  92. package/src/shade/device/timing/profile/SGPT_RECORD_OFFSET.d.ts +13 -0
  93. package/src/shade/device/timing/profile/SGPT_RECORD_OFFSET.d.ts.map +1 -0
  94. package/src/shade/device/timing/profile/SGPT_RECORD_OFFSET.js +23 -0
  95. package/src/shade/device/timing/profile/SGPT_RECORD_SYNC.d.ts +12 -0
  96. package/src/shade/device/timing/profile/SGPT_RECORD_SYNC.d.ts.map +1 -0
  97. package/src/shade/device/timing/profile/SGPT_RECORD_SYNC.js +11 -0
  98. package/src/shade/device/timing/profile/SGPT_RECORD_TYPE.d.ts +18 -0
  99. package/src/shade/device/timing/profile/SGPT_RECORD_TYPE.d.ts.map +1 -0
  100. package/src/shade/device/timing/profile/SGPT_RECORD_TYPE.js +46 -0
  101. package/src/shade/device/timing/profile/frame_graph_extract_topology.d.ts +20 -0
  102. package/src/shade/device/timing/profile/frame_graph_extract_topology.d.ts.map +1 -0
  103. package/src/shade/device/timing/profile/frame_graph_extract_topology.js +174 -0
  104. package/src/shade/device/timing/profile/make_profiling_pass_encoder.d.ts +21 -0
  105. package/src/shade/device/timing/profile/make_profiling_pass_encoder.d.ts.map +1 -0
  106. package/src/shade/device/timing/profile/make_profiling_pass_encoder.js +114 -0
  107. package/src/shade/device/timing/profile/parse_workgroup_size.d.ts +20 -0
  108. package/src/shade/device/timing/profile/parse_workgroup_size.d.ts.map +1 -0
  109. package/src/shade/device/timing/profile/parse_workgroup_size.js +43 -0
  110. package/src/shade/device/timing/profile/sgpt_fourcc.d.ts +18 -0
  111. package/src/shade/device/timing/profile/sgpt_fourcc.d.ts.map +1 -0
  112. package/src/shade/device/timing/profile/sgpt_fourcc.js +34 -0
  113. package/src/shade/device/timing/profile/sgpt_frame_codec.d.ts +42 -0
  114. package/src/shade/device/timing/profile/sgpt_frame_codec.d.ts.map +1 -0
  115. package/src/shade/device/timing/profile/sgpt_frame_codec.js +172 -0
  116. package/src/shade/device/timing/profile/sgpt_meta_codec.d.ts +20 -0
  117. package/src/shade/device/timing/profile/sgpt_meta_codec.d.ts.map +1 -0
  118. package/src/shade/device/timing/profile/sgpt_meta_codec.js +65 -0
  119. package/src/shade/device/timing/profile/sgpt_read_capture.d.ts +19 -0
  120. package/src/shade/device/timing/profile/sgpt_read_capture.d.ts.map +1 -0
  121. package/src/shade/device/timing/profile/sgpt_read_capture.js +134 -0
  122. package/src/shade/device/timing/profile/sgpt_read_header.d.ts +22 -0
  123. package/src/shade/device/timing/profile/sgpt_read_header.d.ts.map +1 -0
  124. package/src/shade/device/timing/profile/sgpt_read_header.js +94 -0
  125. package/src/shade/device/timing/profile/sgpt_read_records.d.ts +27 -0
  126. package/src/shade/device/timing/profile/sgpt_read_records.d.ts.map +1 -0
  127. package/src/shade/device/timing/profile/sgpt_read_records.js +153 -0
  128. package/src/shade/device/timing/profile/sgpt_topology_codec.d.ts +54 -0
  129. package/src/shade/device/timing/profile/sgpt_topology_codec.d.ts.map +1 -0
  130. package/src/shade/device/timing/profile/sgpt_topology_codec.js +329 -0
  131. package/src/shade/device/timing/profile/sgpt_write_header.d.ts +22 -0
  132. package/src/shade/device/timing/profile/sgpt_write_header.d.ts.map +1 -0
  133. package/src/shade/device/timing/profile/sgpt_write_header.js +47 -0
  134. package/src/shade/device/timing/profile/sgpt_write_record.d.ts +23 -0
  135. package/src/shade/device/timing/profile/sgpt_write_record.d.ts.map +1 -0
  136. package/src/shade/device/timing/profile/sgpt_write_record.js +62 -0
  137. package/src/shade/playground/volumetrics_froxel/README.md +88 -0
  138. package/src/shade/playground/volumetrics_froxel/index.html +251 -0
  139. package/src/shade/playground/volumetrics_froxel/main.d.ts +2 -0
  140. package/src/shade/playground/volumetrics_froxel/main.d.ts.map +1 -0
  141. package/src/shade/playground/volumetrics_froxel/main.js +619 -0
  142. package/src/shade/renderer/Renderer.d.ts +34 -0
  143. package/src/shade/renderer/Renderer.d.ts.map +1 -1
  144. package/src/shade/renderer/Renderer.js +2536 -2455
  145. package/src/shade/renderer/volumetrics/NOTES.md +42 -1
  146. package/src/shade/renderer/volumetrics/chunk_camera_ray_planar_depth_scale.d.ts +21 -0
  147. package/src/shade/renderer/volumetrics/chunk_camera_ray_planar_depth_scale.d.ts.map +1 -0
  148. package/src/shade/renderer/volumetrics/chunk_camera_ray_planar_depth_scale.js +47 -0
  149. package/src/shade/renderer/volumetrics/chunk_integrate_optical_depth.d.ts.map +1 -1
  150. package/src/shade/renderer/volumetrics/chunk_integrate_optical_depth.js +19 -8
  151. package/src/shade/renderer/volumetrics/chunk_volumetrics_froxel_content_offset.d.ts +37 -0
  152. package/src/shade/renderer/volumetrics/chunk_volumetrics_froxel_content_offset.d.ts.map +1 -0
  153. package/src/shade/renderer/volumetrics/chunk_volumetrics_froxel_content_offset.js +56 -0
  154. package/src/shade/renderer/volumetrics/graph_build_volumetrics.d.ts.map +1 -1
  155. package/src/shade/renderer/volumetrics/graph_build_volumetrics.js +6 -0
  156. package/src/shade/renderer/volumetrics/shader_volumetrics_build_lighting.d.ts.map +1 -1
  157. package/src/shade/renderer/volumetrics/shader_volumetrics_build_lighting.js +367 -324
  158. package/src/shade/renderer/volumetrics/shader_volumetrics_build_scattering_lut.d.ts.map +1 -1
  159. package/src/shade/renderer/volumetrics/shader_volumetrics_build_scattering_lut.js +14 -3
  160. package/src/shade/renderer/volumetrics/volumetrics_position_world_to_froxel_uvw.d.ts.map +1 -1
  161. package/src/shade/renderer/volumetrics/volumetrics_position_world_to_froxel_uvw.js +48 -36
  162. package/src/engine/save/GameStateLoader.d.ts +0 -49
  163. package/src/engine/save/GameStateLoader.d.ts.map +0 -1
  164. package/src/engine/save/GameStateLoader.js +0 -168
@@ -0,0 +1,159 @@
1
+ /**
2
+ * How a resource's descriptor was recorded. `NONE` covers an imported resource whose descriptor the
3
+ * graph never saw, which is normal rather than a defect.
4
+ */
5
+ export type GPUProfileResourceKind = number;
6
+ export namespace GPUProfileResourceKind {
7
+ let NONE: number;
8
+ let BUFFER: number;
9
+ let TEXTURE: number;
10
+ }
11
+ /**
12
+ * One frame graph pass, as recorded.
13
+ *
14
+ * @author Alex Goldring
15
+ * @copyright Company Named Limited (c) 2026
16
+ */
17
+ export class GPUProfilePass {
18
+ /** @type {number} */
19
+ id: number;
20
+ /** @type {string} */
21
+ name: string;
22
+ /**
23
+ * Index into {@link GPUProfileTopology#scopes}, or -1 when recorded at the top level.
24
+ * @type {number}
25
+ */
26
+ scope: number;
27
+ /**
28
+ * Whether the graph culled this pass. A culled pass is still worth carrying: "why did this run"
29
+ * and "why did this *not* run" are the same question asked from either side.
30
+ * @type {boolean}
31
+ */
32
+ culled: boolean;
33
+ /** @type {boolean} */
34
+ has_side_effects: boolean;
35
+ /** @type {number} */
36
+ ref_count: number;
37
+ /** @type {number[]} resource node ids */
38
+ reads: number[];
39
+ /** @type {number[]} resource node ids */
40
+ writes: number[];
41
+ /** @type {number[]} resource node ids */
42
+ creates: number[];
43
+ }
44
+ /**
45
+ * A named recording region. Scopes nest, and the nesting is the parent chain — this is the
46
+ * hierarchy a flame graph needs, and the graph already has it.
47
+ *
48
+ * @author Alex Goldring
49
+ * @copyright Company Named Limited (c) 2026
50
+ */
51
+ export class GPUProfileScope {
52
+ /** @type {string} */
53
+ name: string;
54
+ /**
55
+ * Index into {@link GPUProfileTopology#scopes}, or -1 for a top-level scope.
56
+ * @type {number}
57
+ */
58
+ parent: number;
59
+ }
60
+ /**
61
+ * One resource **node** — that is, one version of one resource.
62
+ *
63
+ * Keyed by node rather than by registry entry, matching `FrameGraph.exportToJson`. A pass records
64
+ * the node it read or wrote, not the underlying resource, so a registry-keyed model leaves every
65
+ * reference past version 0 dangling.
66
+ *
67
+ * @author Alex Goldring
68
+ * @copyright Company Named Limited (c) 2026
69
+ */
70
+ export class GPUProfileResource {
71
+ /** @type {number} */
72
+ id: number;
73
+ /** @type {string} */
74
+ name: string;
75
+ /** @type {number} */
76
+ version: number;
77
+ /** @type {boolean} */
78
+ transient: boolean;
79
+ /** @type {boolean} */
80
+ imported: boolean;
81
+ /**
82
+ * Id of the pass that produced this version, or -1 — an imported resource as it stood on
83
+ * import, or one created outside any pass.
84
+ * @type {number}
85
+ */
86
+ producer: number;
87
+ /** @type {number} one of {@link GPUProfileResourceKind} */
88
+ kind: number;
89
+ /** Bytes. Buffers only. @type {number} */
90
+ size: number;
91
+ /** `GPUBufferUsage` / `GPUTextureUsage` bitmask. @type {number} */
92
+ usage: number;
93
+ /** Texels. Textures only. @type {number[]} */
94
+ resolution: number[];
95
+ /** @type {number} */
96
+ mip_level_count: number;
97
+ /** @type {number} */
98
+ sample_count: number;
99
+ /** @type {string} */
100
+ format: string;
101
+ /** @type {string} */
102
+ dimension: string;
103
+ /**
104
+ * Declared bytes, computed when the capture was recorded.
105
+ *
106
+ * Computed there rather than here because working a texture's footprint out needs its format's
107
+ * block dimensions, and those live in the engine's format table. Carrying the number instead of
108
+ * the inputs means a reader never has to keep a copy of that table in step with the engine's —
109
+ * and a format the reader has never heard of still reports a size.
110
+ *
111
+ * Declared, not allocated: a pooled allocator may serve a larger block, and an aliasing one may
112
+ * serve the same block to two resources whose lifetimes do not overlap.
113
+ *
114
+ * @type {number}
115
+ */
116
+ byte_size: number;
117
+ }
118
+ /**
119
+ * The shape of one frame: its passes, its resources, and how they depend on each other.
120
+ *
121
+ * **Stored once and referenced by many frames.** A Shade frame graph is nearly identical frame to
122
+ * frame — the same passes over the same resources — and what varies is the timings and the cull
123
+ * decisions. Recording the whole structure per frame is the difference between a capture of tens
124
+ * of megabytes and one of a couple, so topologies are content-hashed and deduplicated, and a frame
125
+ * stores an id.
126
+ *
127
+ * Cull state is the exception and lives here anyway: it varies with the frame, but it varies
128
+ * *with the topology* — a frame in which a different set of passes was culled is a different
129
+ * shape, and gets its own entry.
130
+ *
131
+ * @author Alex Goldring
132
+ * @copyright Company Named Limited (c) 2026
133
+ */
134
+ export class GPUProfileTopology {
135
+ /**
136
+ * Position in the capture's topology list. What a frame refers to.
137
+ * @type {number}
138
+ */
139
+ id: number;
140
+ /** @type {string} */
141
+ name: string;
142
+ /** @type {GPUProfilePass[]} */
143
+ passes: GPUProfilePass[];
144
+ /** @type {GPUProfileScope[]} */
145
+ scopes: GPUProfileScope[];
146
+ /** @type {GPUProfileResource[]} */
147
+ resources: GPUProfileResource[];
148
+ /**
149
+ * Declared bytes across every transient resource, as the graph asked for them.
150
+ *
151
+ * Declared, not allocated: a pooled allocator may hand back a larger block, and an aliased one
152
+ * may hand the same block to two resources whose lifetimes do not overlap. The gap between
153
+ * this and the device's real figure is the aliasing, which is the interesting number.
154
+ *
155
+ * @returns {number}
156
+ */
157
+ get declared_transient_bytes(): number;
158
+ }
159
+ //# sourceMappingURL=GPUProfileTopology.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GPUProfileTopology.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/device/timing/profile/GPUProfileTopology.js"],"names":[],"mappings":";;;;qCAIU,MAAM;;;;;;AAQhB;;;;;GAKG;AACH;IACI,qBAAqB;IACrB,IADW,MAAM,CACV;IAEP,qBAAqB;IACrB,MADW,MAAM,CACP;IAEV;;;OAGG;IACH,OAFU,MAAM,CAEL;IAEX;;;;OAIG;IACH,QAFU,OAAO,CAEF;IAEf,sBAAsB;IACtB,kBADW,OAAO,CACO;IAEzB,qBAAqB;IACrB,WADW,MAAM,CACH;IAEd,yCAAyC;IACzC,OADW,MAAM,EAAE,CACR;IAEX,yCAAyC;IACzC,QADW,MAAM,EAAE,CACP;IAEZ,yCAAyC;IACzC,SADW,MAAM,EAAE,CACN;CAChB;AAED;;;;;;GAMG;AACH;IACI,qBAAqB;IACrB,MADW,MAAM,CACP;IAEV;;;OAGG;IACH,QAFU,MAAM,CAEJ;CACf;AAED;;;;;;;;;GASG;AACH;IACI,qBAAqB;IACrB,IADW,MAAM,CACV;IAEP,qBAAqB;IACrB,MADW,MAAM,CACP;IAEV,qBAAqB;IACrB,SADW,MAAM,CACL;IAEZ,sBAAsB;IACtB,WADW,OAAO,CACA;IAElB,sBAAsB;IACtB,UADW,OAAO,CACD;IAEjB;;;;OAIG;IACH,UAFU,MAAM,CAEF;IAEd,2DAA2D;IAC3D,MADW,MAAM,CACkB;IAEnC,0CAA0C;IAC1C,MADgC,MAAM,CAC7B;IAET,mEAAmE;IACnE,OADyD,MAAM,CACrD;IAEV,8CAA8C;IAC9C,YADkC,MAAM,EAAE,CACnB;IAEvB,qBAAqB;IACrB,iBADW,MAAM,CACG;IAEpB,qBAAqB;IACrB,cADW,MAAM,CACA;IAEjB,qBAAqB;IACrB,QADW,MAAM,CACL;IAEZ,qBAAqB;IACrB,WADW,MAAM,CACF;IAEf;;;;;;;;;;;;OAYG;IACH,WAFU,MAAM,CAEF;CACjB;AAED;;;;;;;;;;;;;;;GAeG;AACH;IACI;;;OAGG;IACH,IAFU,MAAM,CAET;IAEP,qBAAqB;IACrB,MADW,MAAM,CACP;IAEV,+BAA+B;IAC/B,QADW,cAAc,EAAE,CACf;IAEZ,gCAAgC;IAChC,QADW,eAAe,EAAE,CAChB;IAEZ,mCAAmC;IACnC,WADW,kBAAkB,EAAE,CAChB;IAEf;;;;;;;;OAQG;IACH,uCAUC;CACJ"}
@@ -0,0 +1,202 @@
1
+ /**
2
+ * How a resource's descriptor was recorded. `NONE` covers an imported resource whose descriptor the
3
+ * graph never saw, which is normal rather than a defect.
4
+ *
5
+ * @enum {number}
6
+ */
7
+ export const GPUProfileResourceKind = {
8
+ NONE: 0,
9
+ BUFFER: 1,
10
+ TEXTURE: 2
11
+ };
12
+
13
+ /**
14
+ * One frame graph pass, as recorded.
15
+ *
16
+ * @author Alex Goldring
17
+ * @copyright Company Named Limited (c) 2026
18
+ */
19
+ export class GPUProfilePass {
20
+ /** @type {number} */
21
+ id = 0;
22
+
23
+ /** @type {string} */
24
+ name = "";
25
+
26
+ /**
27
+ * Index into {@link GPUProfileTopology#scopes}, or -1 when recorded at the top level.
28
+ * @type {number}
29
+ */
30
+ scope = -1;
31
+
32
+ /**
33
+ * Whether the graph culled this pass. A culled pass is still worth carrying: "why did this run"
34
+ * and "why did this *not* run" are the same question asked from either side.
35
+ * @type {boolean}
36
+ */
37
+ culled = false;
38
+
39
+ /** @type {boolean} */
40
+ has_side_effects = false;
41
+
42
+ /** @type {number} */
43
+ ref_count = 0;
44
+
45
+ /** @type {number[]} resource node ids */
46
+ reads = [];
47
+
48
+ /** @type {number[]} resource node ids */
49
+ writes = [];
50
+
51
+ /** @type {number[]} resource node ids */
52
+ creates = [];
53
+ }
54
+
55
+ /**
56
+ * A named recording region. Scopes nest, and the nesting is the parent chain — this is the
57
+ * hierarchy a flame graph needs, and the graph already has it.
58
+ *
59
+ * @author Alex Goldring
60
+ * @copyright Company Named Limited (c) 2026
61
+ */
62
+ export class GPUProfileScope {
63
+ /** @type {string} */
64
+ name = "";
65
+
66
+ /**
67
+ * Index into {@link GPUProfileTopology#scopes}, or -1 for a top-level scope.
68
+ * @type {number}
69
+ */
70
+ parent = -1;
71
+ }
72
+
73
+ /**
74
+ * One resource **node** — that is, one version of one resource.
75
+ *
76
+ * Keyed by node rather than by registry entry, matching `FrameGraph.exportToJson`. A pass records
77
+ * the node it read or wrote, not the underlying resource, so a registry-keyed model leaves every
78
+ * reference past version 0 dangling.
79
+ *
80
+ * @author Alex Goldring
81
+ * @copyright Company Named Limited (c) 2026
82
+ */
83
+ export class GPUProfileResource {
84
+ /** @type {number} */
85
+ id = 0;
86
+
87
+ /** @type {string} */
88
+ name = "";
89
+
90
+ /** @type {number} */
91
+ version = 0;
92
+
93
+ /** @type {boolean} */
94
+ transient = false;
95
+
96
+ /** @type {boolean} */
97
+ imported = false;
98
+
99
+ /**
100
+ * Id of the pass that produced this version, or -1 — an imported resource as it stood on
101
+ * import, or one created outside any pass.
102
+ * @type {number}
103
+ */
104
+ producer = -1;
105
+
106
+ /** @type {number} one of {@link GPUProfileResourceKind} */
107
+ kind = GPUProfileResourceKind.NONE;
108
+
109
+ /** Bytes. Buffers only. @type {number} */
110
+ size = 0;
111
+
112
+ /** `GPUBufferUsage` / `GPUTextureUsage` bitmask. @type {number} */
113
+ usage = 0;
114
+
115
+ /** Texels. Textures only. @type {number[]} */
116
+ resolution = [0, 0, 0];
117
+
118
+ /** @type {number} */
119
+ mip_level_count = 1;
120
+
121
+ /** @type {number} */
122
+ sample_count = 1;
123
+
124
+ /** @type {string} */
125
+ format = "";
126
+
127
+ /** @type {string} */
128
+ dimension = "";
129
+
130
+ /**
131
+ * Declared bytes, computed when the capture was recorded.
132
+ *
133
+ * Computed there rather than here because working a texture's footprint out needs its format's
134
+ * block dimensions, and those live in the engine's format table. Carrying the number instead of
135
+ * the inputs means a reader never has to keep a copy of that table in step with the engine's —
136
+ * and a format the reader has never heard of still reports a size.
137
+ *
138
+ * Declared, not allocated: a pooled allocator may serve a larger block, and an aliasing one may
139
+ * serve the same block to two resources whose lifetimes do not overlap.
140
+ *
141
+ * @type {number}
142
+ */
143
+ byte_size = 0;
144
+ }
145
+
146
+ /**
147
+ * The shape of one frame: its passes, its resources, and how they depend on each other.
148
+ *
149
+ * **Stored once and referenced by many frames.** A Shade frame graph is nearly identical frame to
150
+ * frame — the same passes over the same resources — and what varies is the timings and the cull
151
+ * decisions. Recording the whole structure per frame is the difference between a capture of tens
152
+ * of megabytes and one of a couple, so topologies are content-hashed and deduplicated, and a frame
153
+ * stores an id.
154
+ *
155
+ * Cull state is the exception and lives here anyway: it varies with the frame, but it varies
156
+ * *with the topology* — a frame in which a different set of passes was culled is a different
157
+ * shape, and gets its own entry.
158
+ *
159
+ * @author Alex Goldring
160
+ * @copyright Company Named Limited (c) 2026
161
+ */
162
+ export class GPUProfileTopology {
163
+ /**
164
+ * Position in the capture's topology list. What a frame refers to.
165
+ * @type {number}
166
+ */
167
+ id = 0;
168
+
169
+ /** @type {string} */
170
+ name = "";
171
+
172
+ /** @type {GPUProfilePass[]} */
173
+ passes = [];
174
+
175
+ /** @type {GPUProfileScope[]} */
176
+ scopes = [];
177
+
178
+ /** @type {GPUProfileResource[]} */
179
+ resources = [];
180
+
181
+ /**
182
+ * Declared bytes across every transient resource, as the graph asked for them.
183
+ *
184
+ * Declared, not allocated: a pooled allocator may hand back a larger block, and an aliased one
185
+ * may hand the same block to two resources whose lifetimes do not overlap. The gap between
186
+ * this and the device's real figure is the aliasing, which is the interesting number.
187
+ *
188
+ * @returns {number}
189
+ */
190
+ get declared_transient_bytes() {
191
+ let total = 0;
192
+
193
+ for (const resource of this.resources) {
194
+ if (resource.transient) {
195
+ total += resource.byte_size;
196
+ }
197
+ }
198
+
199
+ return total;
200
+ }
201
+ }
202
+
@@ -0,0 +1,90 @@
1
+ /**
2
+ * What a GPU pass was asked to do, as opposed to how long it took.
3
+ *
4
+ * Aggregated per pass rather than per call. Most passes issue one dispatch, for which an aggregate
5
+ * *is* the value; the ones that issue many are the ones where a total is what you wanted anyway.
6
+ * Storing every call would multiply a frame record by the draw count, which is the wrong trade for
7
+ * a format meant to be left running.
8
+ *
9
+ * @author Alex Goldring
10
+ * @copyright Company Named Limited (c) 2026
11
+ */
12
+ export class GPUProfileWork {
13
+ /**
14
+ * `dispatchWorkgroups` calls, direct only.
15
+ * @type {number}
16
+ */
17
+ dispatch_count: number;
18
+ /**
19
+ * `dispatchWorkgroupsIndirect` calls.
20
+ *
21
+ * Counted separately because their sizes live in a GPU buffer and are simply not knowable at
22
+ * encode time. Folding them in would make {@link workgroups} read as a total when it is a
23
+ * partial one.
24
+ *
25
+ * @type {number}
26
+ */
27
+ indirect_dispatch_count: number;
28
+ /**
29
+ * Workgroups summed across the direct dispatches, per axis.
30
+ * @type {number[]}
31
+ */
32
+ workgroups: number[];
33
+ /**
34
+ * `draw` and `drawIndexed` calls.
35
+ * @type {number}
36
+ */
37
+ draw_count: number;
38
+ /**
39
+ * `drawIndirect` and `drawIndexedIndirect` calls. Same caveat as
40
+ * {@link indirect_dispatch_count}.
41
+ * @type {number}
42
+ */
43
+ indirect_draw_count: number;
44
+ /**
45
+ * Vertices summed across direct draws.
46
+ * @type {number}
47
+ */
48
+ vertex_count: number;
49
+ /**
50
+ * Indices summed across direct indexed draws.
51
+ * @type {number}
52
+ */
53
+ index_count: number;
54
+ /**
55
+ * Instances summed across direct draws.
56
+ * @type {number}
57
+ */
58
+ instance_count: number;
59
+ /**
60
+ * Label of the pipeline this pass ran, where the pass was built through
61
+ * `constructComputePass` / `constructRenderPass` and one was therefore known.
62
+ * @type {string}
63
+ */
64
+ pipeline: string;
65
+ /**
66
+ * `@workgroup_size` of the compute entry point, or `[0, 0, 0]` when it could not be read —
67
+ * an override-expression size, or a pass whose pipeline was never named.
68
+ * @type {number[]}
69
+ */
70
+ workgroup_size: number[];
71
+ /**
72
+ * Shader invocations this pass asked for: workgroups × workgroup size.
73
+ *
74
+ * Zero when either is unknown, which is a different thing from zero work and is why
75
+ * {@link workgroup_size} is carried rather than assumed. The number worth looking at next to a
76
+ * duration — a dispatch that costs 2 ms over 300 invocations is a dispatch that is the wrong
77
+ * shape.
78
+ *
79
+ * @returns {number}
80
+ */
81
+ get invocation_count(): number;
82
+ /**
83
+ * Whether anything was recorded at all. A pass with nothing here either did no work, or ran at
84
+ * a capture level below {@link GPUProfileLevel.WORKLOAD}.
85
+ *
86
+ * @returns {boolean}
87
+ */
88
+ get is_empty(): boolean;
89
+ }
90
+ //# sourceMappingURL=GPUProfileWork.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GPUProfileWork.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/device/timing/profile/GPUProfileWork.js"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH;IACI;;;OAGG;IACH,gBAFU,MAAM,CAEG;IAEnB;;;;;;;;OAQG;IACH,yBAFU,MAAM,CAEY;IAE5B;;;OAGG;IACH,YAFU,MAAM,EAAE,CAEK;IAEvB;;;OAGG;IACH,YAFU,MAAM,CAED;IAEf;;;;OAIG;IACH,qBAFU,MAAM,CAEQ;IAExB;;;OAGG;IACH,cAFU,MAAM,CAEC;IAEjB;;;OAGG;IACH,aAFU,MAAM,CAEA;IAEhB;;;OAGG;IACH,gBAFU,MAAM,CAEG;IAEnB;;;;OAIG;IACH,UAFU,MAAM,CAEF;IAEd;;;;OAIG;IACH,gBAFU,MAAM,EAAE,CAES;IAE3B;;;;;;;;;OASG;IACH,+BASC;IAED;;;;;OAKG;IACH,wBAMC;CACJ"}
@@ -0,0 +1,115 @@
1
+ /**
2
+ * What a GPU pass was asked to do, as opposed to how long it took.
3
+ *
4
+ * Aggregated per pass rather than per call. Most passes issue one dispatch, for which an aggregate
5
+ * *is* the value; the ones that issue many are the ones where a total is what you wanted anyway.
6
+ * Storing every call would multiply a frame record by the draw count, which is the wrong trade for
7
+ * a format meant to be left running.
8
+ *
9
+ * @author Alex Goldring
10
+ * @copyright Company Named Limited (c) 2026
11
+ */
12
+ export class GPUProfileWork {
13
+ /**
14
+ * `dispatchWorkgroups` calls, direct only.
15
+ * @type {number}
16
+ */
17
+ dispatch_count = 0;
18
+
19
+ /**
20
+ * `dispatchWorkgroupsIndirect` calls.
21
+ *
22
+ * Counted separately because their sizes live in a GPU buffer and are simply not knowable at
23
+ * encode time. Folding them in would make {@link workgroups} read as a total when it is a
24
+ * partial one.
25
+ *
26
+ * @type {number}
27
+ */
28
+ indirect_dispatch_count = 0;
29
+
30
+ /**
31
+ * Workgroups summed across the direct dispatches, per axis.
32
+ * @type {number[]}
33
+ */
34
+ workgroups = [0, 0, 0];
35
+
36
+ /**
37
+ * `draw` and `drawIndexed` calls.
38
+ * @type {number}
39
+ */
40
+ draw_count = 0;
41
+
42
+ /**
43
+ * `drawIndirect` and `drawIndexedIndirect` calls. Same caveat as
44
+ * {@link indirect_dispatch_count}.
45
+ * @type {number}
46
+ */
47
+ indirect_draw_count = 0;
48
+
49
+ /**
50
+ * Vertices summed across direct draws.
51
+ * @type {number}
52
+ */
53
+ vertex_count = 0;
54
+
55
+ /**
56
+ * Indices summed across direct indexed draws.
57
+ * @type {number}
58
+ */
59
+ index_count = 0;
60
+
61
+ /**
62
+ * Instances summed across direct draws.
63
+ * @type {number}
64
+ */
65
+ instance_count = 0;
66
+
67
+ /**
68
+ * Label of the pipeline this pass ran, where the pass was built through
69
+ * `constructComputePass` / `constructRenderPass` and one was therefore known.
70
+ * @type {string}
71
+ */
72
+ pipeline = "";
73
+
74
+ /**
75
+ * `@workgroup_size` of the compute entry point, or `[0, 0, 0]` when it could not be read —
76
+ * an override-expression size, or a pass whose pipeline was never named.
77
+ * @type {number[]}
78
+ */
79
+ workgroup_size = [0, 0, 0];
80
+
81
+ /**
82
+ * Shader invocations this pass asked for: workgroups × workgroup size.
83
+ *
84
+ * Zero when either is unknown, which is a different thing from zero work and is why
85
+ * {@link workgroup_size} is carried rather than assumed. The number worth looking at next to a
86
+ * duration — a dispatch that costs 2 ms over 300 invocations is a dispatch that is the wrong
87
+ * shape.
88
+ *
89
+ * @returns {number}
90
+ */
91
+ get invocation_count() {
92
+ const [wx, wy, wz] = this.workgroups;
93
+ const [sx, sy, sz] = this.workgroup_size;
94
+
95
+ if (sx === 0) {
96
+ return 0;
97
+ }
98
+
99
+ return wx * sx * Math.max(wy, 1) * Math.max(sy, 1) * Math.max(wz, 1) * Math.max(sz, 1);
100
+ }
101
+
102
+ /**
103
+ * Whether anything was recorded at all. A pass with nothing here either did no work, or ran at
104
+ * a capture level below {@link GPUProfileLevel.WORKLOAD}.
105
+ *
106
+ * @returns {boolean}
107
+ */
108
+ get is_empty() {
109
+ return this.dispatch_count === 0
110
+ && this.indirect_dispatch_count === 0
111
+ && this.draw_count === 0
112
+ && this.indirect_draw_count === 0
113
+ && this.pipeline === "";
114
+ }
115
+ }
@@ -0,0 +1,43 @@
1
+ /**
2
+ * @param {number} code one of {@link SGPT_DEFECT}
3
+ * @returns {string}
4
+ */
5
+ export function sgpt_defect_name(code: number): string;
6
+ /**
7
+ * One thing wrong with an `.sgpt` stream.
8
+ *
9
+ * Collected rather than thrown. A capture of the moment a GPU fell over is a capture that ends
10
+ * mid-record, and a reader that refuses it outright discards the only evidence of what happened.
11
+ * The reader gathers defects, returns everything it could decode alongside them, and lets the
12
+ * inspector say plainly what it is showing and what it could not.
13
+ *
14
+ * @author Alex Goldring
15
+ * @copyright Company Named Limited (c) 2026
16
+ */
17
+ export class SGPTDefect {
18
+ /**
19
+ * @param {number} code one of {@link SGPT_DEFECT}
20
+ * @param {string} detail
21
+ * @param {number} [offset]
22
+ */
23
+ constructor(code: number, detail: string, offset?: number);
24
+ /**
25
+ * One of {@link SGPT_DEFECT}.
26
+ * @type {number}
27
+ */
28
+ code: number;
29
+ /**
30
+ * @type {string}
31
+ */
32
+ detail: string;
33
+ /**
34
+ * Byte offset in the stream where the problem was found, or -1 when it is not about one place.
35
+ * @type {number}
36
+ */
37
+ offset: number;
38
+ /**
39
+ * @returns {string}
40
+ */
41
+ toString(): string;
42
+ }
43
+ //# sourceMappingURL=SGPTDefect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SGPTDefect.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/device/timing/profile/SGPTDefect.js"],"names":[],"mappings":"AAoDA;;;GAGG;AACH,uCAHW,MAAM,GACJ,MAAM,CAUlB;AA9DD;;;;;;;;;;GAUG;AACH;IAkBI;;;;OAIG;IACH,kBAJW,MAAM,UACN,MAAM,WACN,MAAM,EAMhB;IA1BD;;;OAGG;IACH,MAFU,MAAM,CAEU;IAE1B;;OAEG;IACH,QAFU,MAAM,CAEJ;IAEZ;;;OAGG;IACH,QAFU,MAAM,CAEJ;IAaZ;;OAEG;IACH,YAFa,MAAM,CAMlB;CACJ"}
@@ -0,0 +1,65 @@
1
+ import { SGPT_DEFECT } from "./SGPT_DEFECT.js";
2
+
3
+ /**
4
+ * One thing wrong with an `.sgpt` stream.
5
+ *
6
+ * Collected rather than thrown. A capture of the moment a GPU fell over is a capture that ends
7
+ * mid-record, and a reader that refuses it outright discards the only evidence of what happened.
8
+ * The reader gathers defects, returns everything it could decode alongside them, and lets the
9
+ * inspector say plainly what it is showing and what it could not.
10
+ *
11
+ * @author Alex Goldring
12
+ * @copyright Company Named Limited (c) 2026
13
+ */
14
+ export class SGPTDefect {
15
+ /**
16
+ * One of {@link SGPT_DEFECT}.
17
+ * @type {number}
18
+ */
19
+ code = SGPT_DEFECT.HEADER;
20
+
21
+ /**
22
+ * @type {string}
23
+ */
24
+ detail = '';
25
+
26
+ /**
27
+ * Byte offset in the stream where the problem was found, or -1 when it is not about one place.
28
+ * @type {number}
29
+ */
30
+ offset = -1;
31
+
32
+ /**
33
+ * @param {number} code one of {@link SGPT_DEFECT}
34
+ * @param {string} detail
35
+ * @param {number} [offset]
36
+ */
37
+ constructor(code, detail, offset = -1) {
38
+ this.code = code;
39
+ this.detail = detail;
40
+ this.offset = offset;
41
+ }
42
+
43
+ /**
44
+ * @returns {string}
45
+ */
46
+ toString() {
47
+ const where = this.offset >= 0 ? ` at byte ${this.offset}` : '';
48
+
49
+ return `${sgpt_defect_name(this.code)}${where}: ${this.detail}`;
50
+ }
51
+ }
52
+
53
+ /**
54
+ * @param {number} code one of {@link SGPT_DEFECT}
55
+ * @returns {string}
56
+ */
57
+ export function sgpt_defect_name(code) {
58
+ for (const name in SGPT_DEFECT) {
59
+ if (SGPT_DEFECT[name] === code) {
60
+ return name;
61
+ }
62
+ }
63
+
64
+ return `UNKNOWN(${code})`;
65
+ }