@forgeax/engine-render 0.1.6 → 0.1.7

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 (151) hide show
  1. package/README.md +139 -0
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/__tests__/gpu-driven-indirect-raster-evidence.d.ts.map +1 -1
  4. package/dist/assembly/factory.d.ts +7 -0
  5. package/dist/assembly/factory.d.ts.map +1 -1
  6. package/dist/assembly/material/assembly.d.ts.map +1 -1
  7. package/dist/authoring.d.ts +1 -0
  8. package/dist/authoring.d.ts.map +1 -1
  9. package/dist/authoring.mjs +1 -1
  10. package/dist/{chunk-QC4VW3XJ.mjs → chunk-HCOGPHKS.mjs} +17 -3
  11. package/dist/chunk-HCOGPHKS.mjs.map +1 -0
  12. package/dist/chunk-YEJIUW7D.mjs +1152 -0
  13. package/dist/chunk-YEJIUW7D.mjs.map +1 -0
  14. package/dist/components/__tests__/points-lines-admission.unit.test.d.ts +2 -0
  15. package/dist/components/__tests__/points-lines-admission.unit.test.d.ts.map +1 -0
  16. package/dist/components/__tests__/points-lines-schema.unit.test.d.ts +2 -0
  17. package/dist/components/__tests__/points-lines-schema.unit.test.d.ts.map +1 -0
  18. package/dist/components/index.d.ts +2 -0
  19. package/dist/components/index.d.ts.map +1 -1
  20. package/dist/components/lines.d.ts +5 -0
  21. package/dist/components/lines.d.ts.map +1 -0
  22. package/dist/components/points.d.ts +15 -0
  23. package/dist/components/points.d.ts.map +1 -0
  24. package/dist/construct-renderer.mjs +952 -497
  25. package/dist/construct-renderer.mjs.map +1 -1
  26. package/dist/errors/render.d.ts +82 -1
  27. package/dist/errors/render.d.ts.map +1 -1
  28. package/dist/features/render-graph-raster.d.ts +5 -1
  29. package/dist/features/render-graph-raster.d.ts.map +1 -1
  30. package/dist/gpu-driven/production-raster.d.ts.map +1 -1
  31. package/dist/index.d.ts +4 -0
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.mjs +4 -2
  34. package/dist/index.mjs.map +1 -1
  35. package/dist/inspection-types.d.ts +3 -0
  36. package/dist/inspection-types.d.ts.map +1 -1
  37. package/dist/pbr-pipeline.d.ts +2 -0
  38. package/dist/pbr-pipeline.d.ts.map +1 -1
  39. package/dist/plugin.d.ts.map +1 -1
  40. package/dist/points-lines/__tests__/bounds.unit.test.d.ts +2 -0
  41. package/dist/points-lines/__tests__/bounds.unit.test.d.ts.map +1 -0
  42. package/dist/points-lines/__tests__/cache-recovery.unit.test.d.ts +2 -0
  43. package/dist/points-lines/__tests__/cache-recovery.unit.test.d.ts.map +1 -0
  44. package/dist/points-lines/__tests__/inspection-lanes.integration.test.d.ts +2 -0
  45. package/dist/points-lines/__tests__/inspection-lanes.integration.test.d.ts.map +1 -0
  46. package/dist/points-lines/__tests__/inspection.unit.test.d.ts +2 -0
  47. package/dist/points-lines/__tests__/inspection.unit.test.d.ts.map +1 -0
  48. package/dist/points-lines/__tests__/lane-structural.integration.test.d.ts +2 -0
  49. package/dist/points-lines/__tests__/lane-structural.integration.test.d.ts.map +1 -0
  50. package/dist/points-lines/__tests__/points-lines.bench.d.ts +2 -0
  51. package/dist/points-lines/__tests__/points-lines.bench.d.ts.map +1 -0
  52. package/dist/points-lines/__tests__/raster-lane.integration.test.d.ts +2 -0
  53. package/dist/points-lines/__tests__/raster-lane.integration.test.d.ts.map +1 -0
  54. package/dist/points-lines/__tests__/snapshot.unit.test.d.ts +2 -0
  55. package/dist/points-lines/__tests__/snapshot.unit.test.d.ts.map +1 -0
  56. package/dist/points-lines/__tests__/view-ubo.unit.test.d.ts +2 -0
  57. package/dist/points-lines/__tests__/view-ubo.unit.test.d.ts.map +1 -0
  58. package/dist/points-lines/admission.d.ts +36 -0
  59. package/dist/points-lines/admission.d.ts.map +1 -0
  60. package/dist/points-lines/bounds.d.ts +8 -0
  61. package/dist/points-lines/bounds.d.ts.map +1 -0
  62. package/dist/points-lines/expansion-cache.d.ts +28 -0
  63. package/dist/points-lines/expansion-cache.d.ts.map +1 -0
  64. package/dist/points-lines/inspection.d.ts +53 -0
  65. package/dist/points-lines/inspection.d.ts.map +1 -0
  66. package/dist/points-lines/prepare.d.ts +67 -0
  67. package/dist/points-lines/prepare.d.ts.map +1 -0
  68. package/dist/points-lines/record.d.ts +60 -0
  69. package/dist/points-lines/record.d.ts.map +1 -0
  70. package/dist/points-lines/snapshot.d.ts +49 -0
  71. package/dist/points-lines/snapshot.d.ts.map +1 -0
  72. package/dist/record/frame-lighting.d.ts.map +1 -1
  73. package/dist/record/frame.d.ts +1 -1
  74. package/dist/record/frame.d.ts.map +1 -1
  75. package/dist/record/main-pass-geometry.d.ts +7 -0
  76. package/dist/record/main-pass-geometry.d.ts.map +1 -1
  77. package/dist/record/main-pass.d.ts.map +1 -1
  78. package/dist/record/render-context.d.ts +17 -0
  79. package/dist/record/render-context.d.ts.map +1 -1
  80. package/dist/record/shadow-pass.d.ts.map +1 -1
  81. package/dist/record/skybox-post-pass.d.ts.map +1 -1
  82. package/dist/record/typed-frame-graph.d.ts.map +1 -1
  83. package/dist/record/view-ubo.d.ts +6 -0
  84. package/dist/record/view-ubo.d.ts.map +1 -1
  85. package/dist/render-contract.d.ts +10 -2
  86. package/dist/render-contract.d.ts.map +1 -1
  87. package/dist/render-system-extract.d.ts +3 -0
  88. package/dist/render-system-extract.d.ts.map +1 -1
  89. package/dist/render-system.d.ts +4 -1
  90. package/dist/render-system.d.ts.map +1 -1
  91. package/dist/scene/render-scene-types.d.ts +3 -0
  92. package/dist/scene/render-scene-types.d.ts.map +1 -1
  93. package/dist/scene/render-scene.d.ts +7 -0
  94. package/dist/scene/render-scene.d.ts.map +1 -1
  95. package/package.json +19 -19
  96. package/src/__tests__/authoring-path.unit.test.ts +9 -0
  97. package/src/__tests__/gpu-driven-indirect-raster-evidence.ts +12 -2
  98. package/src/__tests__/material-cooked-projection.unit.test.ts +29 -7
  99. package/src/__tests__/material-static-dynamic-route.unit.test.ts +28 -28
  100. package/src/__tests__/render-error-code-owner.test-d.ts +6 -0
  101. package/src/__tests__/render-error-exhaustive.test-d.ts +19 -0
  102. package/src/__tests__/renderer-factory-material-contract.unit.test.ts +38 -0
  103. package/src/assembly/factory.ts +72 -3
  104. package/src/assembly/material/assembly.ts +2 -5
  105. package/src/authoring.ts +1 -0
  106. package/src/components/__tests__/points-lines-admission.unit.test.ts +219 -0
  107. package/src/components/__tests__/points-lines-schema.unit.test.ts +56 -0
  108. package/src/components/index.ts +7 -0
  109. package/src/components/lines.ts +18 -0
  110. package/src/components/points.ts +40 -0
  111. package/src/errors/render.ts +144 -1
  112. package/src/features/render-graph-raster.ts +22 -3
  113. package/src/gpu-driven/production-raster.ts +6 -1
  114. package/src/index.ts +17 -0
  115. package/src/inspection-types.ts +4 -0
  116. package/src/pbr-pipeline.ts +8 -1
  117. package/src/plugin.ts +4 -0
  118. package/src/points-lines/__tests__/bounds.unit.test.ts +21 -0
  119. package/src/points-lines/__tests__/cache-recovery.unit.test.ts +157 -0
  120. package/src/points-lines/__tests__/inspection-lanes.integration.test.ts +146 -0
  121. package/src/points-lines/__tests__/inspection.unit.test.ts +173 -0
  122. package/src/points-lines/__tests__/lane-structural.integration.test.ts +122 -0
  123. package/src/points-lines/__tests__/points-lines.bench.ts +400 -0
  124. package/src/points-lines/__tests__/raster-lane.integration.test.ts +44 -0
  125. package/src/points-lines/__tests__/snapshot.unit.test.ts +101 -0
  126. package/src/points-lines/__tests__/view-ubo.unit.test.ts +73 -0
  127. package/src/points-lines/admission.ts +238 -0
  128. package/src/points-lines/bounds.ts +23 -0
  129. package/src/points-lines/expansion-cache.ts +215 -0
  130. package/src/points-lines/inspection.ts +97 -0
  131. package/src/points-lines/prepare.ts +177 -0
  132. package/src/points-lines/record.ts +125 -0
  133. package/src/points-lines/snapshot.ts +130 -0
  134. package/src/record/frame-lighting.ts +14 -2
  135. package/src/record/frame.ts +12 -1
  136. package/src/record/main-pass-geometry.ts +92 -0
  137. package/src/record/main-pass-sprite-draws.ts +1 -1
  138. package/src/record/main-pass.ts +6 -3
  139. package/src/record/render-context.ts +20 -0
  140. package/src/record/shadow-pass.ts +16 -5
  141. package/src/record/skybox-post-pass.ts +2 -1
  142. package/src/record/typed-frame-graph.ts +17 -16
  143. package/src/record/view-ubo.ts +47 -0
  144. package/src/render-contract.ts +13 -2
  145. package/src/render-system-extract.ts +71 -8
  146. package/src/render-system.ts +304 -2
  147. package/src/scene/render-scene-types.ts +3 -0
  148. package/src/scene/render-scene.ts +57 -2
  149. package/dist/chunk-QC4VW3XJ.mjs.map +0 -1
  150. package/dist/chunk-SCRSAK5B.mjs +0 -480
  151. package/dist/chunk-SCRSAK5B.mjs.map +0 -1
package/README.md CHANGED
@@ -90,6 +90,15 @@ not expose a timing controller or a second membership-specific API.
90
90
 
91
91
  ## RenderFeature: the producer seam (first-read index)
92
92
 
93
+ ### Material contract projection
94
+
95
+ Render consumes only the Pack-owned material publication projection. Its
96
+ inputs are runtime bool/value data, composed module slots, and the closed
97
+ compiler context; render never authors, cooks, writes DDC, or selects a
98
+ fallback material. The projection preserves `layoutIdentity`,
99
+ `programIdentity`, `cookIdentity`, and `materialPublicationIdentity` so a
100
+ stale draw can be traced to the first producer divergence.
101
+
93
102
  The public route is one `RenderFeature<FrameData>` through the Standard
94
103
  Pipeline and the active RenderGraph pass. In the examples below, `type FrameData`
95
104
  is the producer-owned extracted value. A feature extracts one frame value,
@@ -131,6 +140,136 @@ uses the neutral engine material.
131
140
 
132
141
  The render path is `MaterialAsset` -> extract snapshot -> prepare resources -> record the per-slot `coordinates` and values. The effective `parent` is already resolved before extract. If a material contract or reflection binding fails, preserve the structured error and repair the source contract or cooked module before drawing again; that is the recovery route. The render package owns consumption, not material import or cook policy.
133
142
 
143
+ ## Points and Lines authoring (M1)
144
+
145
+ Points and Lines are first-class render components. Their geometry remains a
146
+ normal `MeshAsset`, and their material remains the engine-owned
147
+ `Materials.unlit` asset. The M1 path validates the complete candidate before
148
+ any render publication; it does not add a second mesh, material, CLI, RPC, or
149
+ manifest authority.
150
+
151
+ ```ts
152
+ import { Lines, Materials, PointShapeValue, Points, admitPointsLines } from '@forgeax/engine-render';
153
+ import { World } from '@forgeax/engine-ecs';
154
+ import type { MeshAsset } from '@forgeax/engine-types';
155
+
156
+ const positions = new Float32Array([0, 0, 0, 1, 0, 0, 2, 0, 0]);
157
+ const pointMesh = {
158
+ kind: 'mesh',
159
+ vertices: positions,
160
+ attributes: { position: positions },
161
+ submeshes: [{
162
+ indexOffset: 0,
163
+ indexCount: 0,
164
+ vertexCount: 3,
165
+ topology: 'point-list',
166
+ materialSlot: 0,
167
+ }],
168
+ materialSlots: [{ slotName: 'default' }],
169
+ } satisfies MeshAsset;
170
+ const material = Materials.unlit([1, 0.5, 0.25, 1], { castShadow: false });
171
+ const world = new World();
172
+ const entity = world.spawn({
173
+ component: Points,
174
+ data: { sizePx: 4, shape: PointShapeValue.circle },
175
+ }).unwrap();
176
+ const admitted = admitPointsLines({
177
+ entity,
178
+ points: { sizePx: 4, shape: PointShapeValue.circle },
179
+ mesh: pointMesh,
180
+ material,
181
+ });
182
+ if (!admitted.ok) throw new Error(admitted.error.hint);
183
+
184
+ world.spawn({ component: Lines, data: { widthPx: 2 } }).unwrap();
185
+ ```
186
+
187
+ The style vocabulary is deliberately small in M1:
188
+
189
+ | Component | Field | Default | Accepted values |
190
+ |:--|:--|--:|:--|
191
+ | `Points` | `sizePx` | `4` | finite number greater than `0` |
192
+ | `Points` | `shape` | `square` | `square` or `circle` |
193
+ | `Lines` | `widthPx` | `1` | finite number greater than `0` |
194
+
195
+ Admission consumes one style component, one ordinary mesh topology, and one
196
+ unlit forward material. Indexed and non-indexed `point-list` meshes are valid
197
+ for `Points`; indexed and non-indexed paired `line-list` meshes are valid for
198
+ `Lines`.
199
+
200
+ | Candidate | M1 result | Reason |
201
+ |:--|:--:|:--|
202
+ | `Points` + `point-list` + finite positive `sizePx` + unlit forward material | supported | `square` and `circle` are the only point shapes |
203
+ | `Lines` + paired `line-list` + finite positive `widthPx` + unlit forward material | supported | each pair is one line segment |
204
+ | `line-strip`, triangle topology, mixed submeshes, or an odd line-list tail | refused | topology cannot be inferred or admitted atomically |
205
+ | both `Points` and `Lines` on one candidate | refused | one entity has one style lane |
206
+ | `Materials.standard`, shadow-caster, deferred, or another shader module | refused | M1 accepts one engine-owned unlit forward pass |
207
+ | candidate count over `maxPoints` or `maxSegments` | refused | bounded admission prevents partial publication |
208
+
209
+ When admission refuses a candidate, consume the structured result rather than
210
+ parsing its message. The result exposes `.code`, `.expected`, `.hint`, and a
211
+ code-specific `.detail` containing the relevant entity, component, mesh,
212
+ material, submesh, lane, generation, or stage facts:
213
+
214
+ ```ts
215
+ const result = admitPointsLines({ entity, points: {}, mesh: pointMesh, material });
216
+ if (!result.ok) {
217
+ console.error(result.error.code);
218
+ console.error(result.error.expected);
219
+ console.error(result.error.hint);
220
+ console.error(result.error.detail);
221
+ }
222
+ ```
223
+
224
+ M1 intentionally refuses strip expansion, joins, caps, dashes, picking, and
225
+ visible point/line draw preparation. Those are later implementation lanes, not
226
+ implicit fallbacks in authoring code.
227
+
228
+ ## Points and Lines runtime contract
229
+
230
+ The complete public closure is `MeshAsset` topology, one `Points` or `Lines`
231
+ component, `Materials.unlit`, and the Standard renderer. The owner retains the
232
+ source view, derives expanded geometry during prepare, and records the dedicated
233
+ points-lines pipeline in the active main geometry pass. Applications do not
234
+ create a second mesh, GPU buffer, shader module, cache, recovery ledger, or
235
+ backend branch.
236
+
237
+ | Surface | Supported contract | Refused or not claimed |
238
+ |:--|:--|:--|
239
+ | topology | indexed or non-indexed `point-list` and paired `line-list` | strips, triangles, mixed topology, and odd line tails |
240
+ | style | finite positive `Points.sizePx` and `Lines.widthPx`; circle or square points | negative, non-finite, or lane-conflicting values |
241
+ | material | engine-owned `Materials.unlit` forward material | standard/PBR, deferred, shadow-only, or custom runtime shader |
242
+ | capability lane | direct WebGPU runtime; clustered unlit preserves the same authoring contract | CPU and WebGL2 require their declared capability route; no pixel result is inferred from RhiNull |
243
+ | structural lane | RhiNull records retained projection, preparation, bindings, and draw shape | RhiNull is never hardware or pixel evidence |
244
+
245
+ Prepare and record remain one lifecycle. A failed result is an owner fact, not a
246
+ request to fall back to a generic mesh draw. Inspect the structured error and
247
+ repair the source or producer, then retry the same renderer:
248
+
249
+ ```ts
250
+ const inspection = renderer.inspect();
251
+ const pointsLines = inspection.renderScene.pointsLines;
252
+ // Repair the named source or producer, then retry inspection and draw.
253
+ report(pointsLines);
254
+ ```
255
+
256
+ Inspection reports source bytes, derived bytes, vertex/index counts, cache
257
+ state, upload state, draw count, lane, and the retained `lastKnownGood` state.
258
+ Recovery is `inspect -> producer rebuild or cold-cook -> prepare -> record`.
259
+ It never publishes a partial expansion and never hides a stale-generation or
260
+ missing-resource error.
261
+
262
+ For visual evidence, use the topology probe and retain its raw screenshot,
263
+ readback, source/derived byte counts, draw count, and validation errors. A
264
+ focused direct-WebGPU probe is evidence for that lane only. The repository-wide
265
+ `pnpm test:browser` gate was explicitly skipped by human override in this
266
+ milestone and must not be reported as passed; the controlled Dawn attempt
267
+ timed out during environment build before Dawn Vitest ran.
268
+
269
+ The M5 boundary does not include strip joins, caps, dashes, picking, a new CLI
270
+ or RPC operation, application-local WGSL, a second Geometry factory, or a
271
+ separate cache/recovery authority.
272
+
134
273
  > [!IMPORTANT]
135
274
  > Owner: render vocabulary and the extract → prepare → record frame boundary. Runtime selects concrete services and calls this package; it does not re-own these tokens.
136
275