@forgeax/engine-render 0.1.34 → 0.1.36

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 (273) hide show
  1. package/README.md +69 -3
  2. package/dist/assembly/device-feature-admission.d.ts +2 -2
  3. package/dist/assembly/host-contract.d.ts +3 -2
  4. package/dist/assembly/host-contract.d.ts.map +1 -1
  5. package/dist/assembly/recovery/renderer-recover.d.ts.map +1 -1
  6. package/dist/assembly/render-target-host.d.ts +5 -0
  7. package/dist/assembly/render-target-host.d.ts.map +1 -1
  8. package/dist/assembly/renderer-facade.d.ts.map +1 -1
  9. package/dist/assembly/webgpu-renderer.d.ts +1 -0
  10. package/dist/assembly/webgpu-renderer.d.ts.map +1 -1
  11. package/dist/assembly/webgpu-vertex-layouts.d.ts.map +1 -1
  12. package/dist/authoring.mjs +2 -4
  13. package/dist/authoring.mjs.map +1 -1
  14. package/dist/chunk-2OZAS3WU.mjs +3489 -0
  15. package/dist/chunk-2OZAS3WU.mjs.map +1 -0
  16. package/dist/{chunk-UI5SFODX.mjs → chunk-BZQ4CDRF.mjs} +2338 -1991
  17. package/dist/chunk-BZQ4CDRF.mjs.map +1 -0
  18. package/dist/{chunk-MKDIT2EM.mjs → chunk-CJOV2XLO.mjs} +216 -261
  19. package/dist/chunk-CJOV2XLO.mjs.map +1 -0
  20. package/dist/chunk-D6WSBXJ2.mjs +1842 -0
  21. package/dist/chunk-D6WSBXJ2.mjs.map +1 -0
  22. package/dist/{chunk-HEB564WF.mjs → chunk-DRF6OULX.mjs} +4 -4
  23. package/dist/{chunk-HEB564WF.mjs.map → chunk-DRF6OULX.mjs.map} +1 -1
  24. package/dist/{chunk-OCDLEI6I.mjs → chunk-OB5WAFYH.mjs} +117 -5
  25. package/dist/chunk-OB5WAFYH.mjs.map +1 -0
  26. package/dist/{chunk-ODZWR6JQ.mjs → chunk-OEYKKMXG.mjs} +2042 -27
  27. package/dist/chunk-OEYKKMXG.mjs.map +1 -0
  28. package/dist/chunk-RIPAEGI6.mjs +48 -0
  29. package/dist/chunk-RIPAEGI6.mjs.map +1 -0
  30. package/dist/{chunk-ELJFJ2BU.mjs → chunk-X2KA6WHM.mjs} +29 -4
  31. package/dist/chunk-X2KA6WHM.mjs.map +1 -0
  32. package/dist/{chunk-BLXGONR2.mjs → chunk-XSFB7XXQ.mjs} +51 -4
  33. package/dist/chunk-XSFB7XXQ.mjs.map +1 -0
  34. package/dist/cloud/frame-context.d.ts +2 -2
  35. package/dist/cloud/frame-context.d.ts.map +1 -1
  36. package/dist/construct-renderer.mjs +936 -2140
  37. package/dist/construct-renderer.mjs.map +1 -1
  38. package/dist/device/device-scope.d.ts.map +1 -1
  39. package/dist/device/gpu-residency.d.ts +19 -19
  40. package/dist/device/gpu-residency.d.ts.map +1 -1
  41. package/dist/errors/render.d.ts +3 -2
  42. package/dist/errors/render.d.ts.map +1 -1
  43. package/dist/extract/material-context.d.ts +7 -0
  44. package/dist/extract/material-context.d.ts.map +1 -0
  45. package/dist/features/host.d.ts +5 -0
  46. package/dist/features/host.d.ts.map +1 -1
  47. package/dist/features/particle-mesh-layout.d.ts +19 -0
  48. package/dist/features/particle-mesh-layout.d.ts.map +1 -0
  49. package/dist/features/plan.d.ts +2 -0
  50. package/dist/features/plan.d.ts.map +1 -1
  51. package/dist/features/types.d.ts +8 -0
  52. package/dist/features/types.d.ts.map +1 -1
  53. package/dist/glyph-text-layout-system.d.ts +1 -1
  54. package/dist/glyph-text-layout-system.d.ts.map +1 -1
  55. package/dist/gpu-driven/production-raster.d.ts +1 -1
  56. package/dist/gpu-driven/production-raster.d.ts.map +1 -1
  57. package/dist/gpu-driven/shadow-ownership.d.ts +3 -3
  58. package/dist/gpu-driven/shadow-ownership.d.ts.map +1 -1
  59. package/dist/gpu-driven/shadow-views.d.ts +1 -1
  60. package/dist/gpu-driven/shadow-views.d.ts.map +1 -1
  61. package/dist/gpu-driven/view-gpu.d.ts +1 -1
  62. package/dist/gpu-driven/view-gpu.d.ts.map +1 -1
  63. package/dist/ibl/frame-resources.d.ts.map +1 -1
  64. package/dist/ibl/skylight-bind-group.d.ts +4 -4
  65. package/dist/ibl/skylight-bind-group.d.ts.map +1 -1
  66. package/dist/index.d.ts +3 -0
  67. package/dist/index.d.ts.map +1 -1
  68. package/dist/index.mjs +542 -9
  69. package/dist/index.mjs.map +1 -1
  70. package/dist/instances.d.ts +3 -4
  71. package/dist/instances.d.ts.map +1 -1
  72. package/dist/internal.mjs +7 -8
  73. package/dist/internal.mjs.map +1 -1
  74. package/dist/pbr-pipeline.d.ts +3 -3
  75. package/dist/pbr-pipeline.d.ts.map +1 -1
  76. package/dist/pipeline/standard-output/lut-gpu.d.ts +2 -2
  77. package/dist/pipeline/standard-output/lut-gpu.d.ts.map +1 -1
  78. package/dist/pipeline/standard-output/resources.d.ts +2 -2
  79. package/dist/pipeline/standard-output/resources.d.ts.map +1 -1
  80. package/dist/publication/contract.d.ts +77 -0
  81. package/dist/publication/contract.d.ts.map +1 -0
  82. package/dist/publication/dependencies.d.ts +7 -0
  83. package/dist/publication/dependencies.d.ts.map +1 -0
  84. package/dist/publication/prepare-geometry.d.ts +9 -0
  85. package/dist/publication/prepare-geometry.d.ts.map +1 -0
  86. package/dist/publication/programs.d.ts +5 -0
  87. package/dist/publication/programs.d.ts.map +1 -0
  88. package/dist/publication/publisher.d.ts +34 -0
  89. package/dist/publication/publisher.d.ts.map +1 -0
  90. package/dist/publication/receiver.d.ts +29 -0
  91. package/dist/publication/receiver.d.ts.map +1 -0
  92. package/dist/publication/resource-scope.d.ts +18 -0
  93. package/dist/publication/resource-scope.d.ts.map +1 -0
  94. package/dist/publication/targets.d.ts +33 -0
  95. package/dist/publication/targets.d.ts.map +1 -0
  96. package/dist/publication/video.d.ts +5 -0
  97. package/dist/publication/video.d.ts.map +1 -0
  98. package/dist/record/fold-buckets.d.ts +3 -3
  99. package/dist/record/fold-buckets.d.ts.map +1 -1
  100. package/dist/record/frame-snapshot.d.ts +6 -6
  101. package/dist/record/frame-snapshot.d.ts.map +1 -1
  102. package/dist/record/frame.d.ts +5 -4
  103. package/dist/record/frame.d.ts.map +1 -1
  104. package/dist/record/helpers.d.ts +2 -2
  105. package/dist/record/helpers.d.ts.map +1 -1
  106. package/dist/record/main-pass-geometry.d.ts +2 -2
  107. package/dist/record/main-pass-geometry.d.ts.map +1 -1
  108. package/dist/record/main-pass-material.d.ts +7 -9
  109. package/dist/record/main-pass-material.d.ts.map +1 -1
  110. package/dist/record/main-pass-sprite-draws.d.ts +3 -16
  111. package/dist/record/main-pass-sprite-draws.d.ts.map +1 -1
  112. package/dist/record/main-pass.d.ts.map +1 -1
  113. package/dist/record/prepared-material-bindings.d.ts +2 -3
  114. package/dist/record/prepared-material-bindings.d.ts.map +1 -1
  115. package/dist/record/render-context.d.ts +4 -2
  116. package/dist/record/render-context.d.ts.map +1 -1
  117. package/dist/record/shadow-pass.d.ts +2 -2
  118. package/dist/record/shadow-pass.d.ts.map +1 -1
  119. package/dist/record/sprite-instance-buffer.d.ts +31 -0
  120. package/dist/record/sprite-instance-buffer.d.ts.map +1 -0
  121. package/dist/record/target-capture-graph.d.ts +19 -0
  122. package/dist/record/target-capture-graph.d.ts.map +1 -0
  123. package/dist/record/typed-frame-graph.d.ts +2 -13
  124. package/dist/record/typed-frame-graph.d.ts.map +1 -1
  125. package/dist/record/view-ubo.d.ts.map +1 -1
  126. package/dist/record/volume-params.d.ts +2 -2
  127. package/dist/record/volume-params.d.ts.map +1 -1
  128. package/dist/recovery/render-system-candidate.d.ts +5 -12
  129. package/dist/recovery/render-system-candidate.d.ts.map +1 -1
  130. package/dist/render-contract.d.ts +4 -1
  131. package/dist/render-contract.d.ts.map +1 -1
  132. package/dist/render-system-extract-tail.d.ts.map +1 -1
  133. package/dist/render-system-extract.d.ts +2 -0
  134. package/dist/render-system-extract.d.ts.map +1 -1
  135. package/dist/render-system-presentation.d.ts +2 -2
  136. package/dist/render-system-presentation.d.ts.map +1 -1
  137. package/dist/render-system-projections.d.ts +3 -2
  138. package/dist/render-system-projections.d.ts.map +1 -1
  139. package/dist/render-system-residency.d.ts +2 -2
  140. package/dist/render-system-residency.d.ts.map +1 -1
  141. package/dist/render-system.d.ts +3 -7
  142. package/dist/render-system.d.ts.map +1 -1
  143. package/dist/scene/render-scene.d.ts +8 -4
  144. package/dist/scene/render-scene.d.ts.map +1 -1
  145. package/dist/scene/render-source.d.ts +42 -0
  146. package/dist/scene/render-source.d.ts.map +1 -0
  147. package/dist/scene/source-systems.d.ts +6 -0
  148. package/dist/scene/source-systems.d.ts.map +1 -0
  149. package/dist/systems/skin-palette-allocator.d.ts.map +1 -1
  150. package/dist/systems/skin-palette-types.d.ts +10 -0
  151. package/dist/systems/skin-palette-types.d.ts.map +1 -1
  152. package/dist/systems/transparent-dispatch.d.ts +2 -2
  153. package/dist/systems/transparent-dispatch.d.ts.map +1 -1
  154. package/dist/systems/transparent-sort-config.d.ts +2 -1
  155. package/dist/systems/transparent-sort-config.d.ts.map +1 -1
  156. package/dist/temporal/index.mjs +6 -7
  157. package/dist/typed-shadow-passes.d.ts.map +1 -1
  158. package/package.json +21 -21
  159. package/src/__tests__/auto-exposure-transaction.integration.test.ts +4 -9
  160. package/src/__tests__/device-feature-admission.unit.test.ts +3 -2
  161. package/src/__tests__/device-scope-lifecycle.unit.test.ts +26 -0
  162. package/src/__tests__/gpu-driven-pbr.dawn.test.ts +3 -4
  163. package/src/__tests__/gpu-driven-production.integration.test.ts +18 -1
  164. package/src/__tests__/gpu-driven-shadow-views.unit.test.ts +23 -0
  165. package/src/__tests__/ktx2-basis-gpu-consumer.dawn.test.ts +4 -1
  166. package/src/__tests__/main-pass-material-medium-selection.unit.test.ts +0 -1
  167. package/src/__tests__/material-vertex-texture.browser.test.ts +7 -0
  168. package/src/__tests__/material-vertex-texture.dawn.test.ts +7 -0
  169. package/src/__tests__/material-vertex-texture.fixture.ts +31 -0
  170. package/src/__tests__/materials-standard-contract.unit.test.ts +0 -1
  171. package/src/__tests__/physical-clearcoat.integration.test.ts +23 -23
  172. package/src/__tests__/physical-material-budget.unit.test.ts +40 -0
  173. package/src/__tests__/recovery-candidate-prepare.contract.test.ts +5 -0
  174. package/src/__tests__/render-error-code-owner.test-d.ts +1 -0
  175. package/src/__tests__/renderer-factory-material-contract.unit.test.ts +107 -5
  176. package/src/__tests__/runtime-material-program.integration.test.ts +79 -0
  177. package/src/__tests__/vertex-layouts-ssot.unit.test.ts +23 -3
  178. package/src/assembly/device-feature-admission.ts +2 -2
  179. package/src/assembly/host-contract.ts +5 -2
  180. package/src/assembly/recovery/renderer-recover.ts +9 -0
  181. package/src/assembly/render-target-host.ts +57 -47
  182. package/src/assembly/renderer-facade.ts +3 -1
  183. package/src/assembly/webgpu-ready.ts +1 -1
  184. package/src/assembly/webgpu-renderer.ts +101 -70
  185. package/src/assembly/webgpu-vertex-layouts.ts +2 -9
  186. package/src/cloud/frame-context.ts +2 -2
  187. package/src/device/device-scope.ts +3 -0
  188. package/src/device/gpu-residency.ts +26 -25
  189. package/src/errors/render.ts +3 -1
  190. package/src/extract/material-context.ts +21 -0
  191. package/src/features/host.ts +13 -5
  192. package/src/features/particle-mesh-layout.ts +25 -0
  193. package/src/features/plan.ts +2 -0
  194. package/src/features/types.ts +8 -0
  195. package/src/glyph-text-layout-system.ts +2 -2
  196. package/src/gpu-driven/production-raster.ts +9 -3
  197. package/src/gpu-driven/shadow-ownership.ts +3 -3
  198. package/src/gpu-driven/shadow-views.ts +27 -2
  199. package/src/gpu-driven/view-gpu.ts +5 -0
  200. package/src/ibl/frame-resources.ts +0 -1
  201. package/src/ibl/skylight-bind-group.ts +13 -25
  202. package/src/index.ts +9 -0
  203. package/src/instances.ts +9 -6
  204. package/src/pbr-pipeline.ts +15 -18
  205. package/src/pipeline/standard-output/lut-gpu.ts +3 -3
  206. package/src/pipeline/standard-output/resources.ts +2 -2
  207. package/src/publication/__tests__/derived-geometry.integration.test.ts +177 -0
  208. package/src/publication/__tests__/features.integration.test.ts +173 -0
  209. package/src/publication/__tests__/programs.unit.test.ts +25 -0
  210. package/src/publication/__tests__/publication.integration.test.ts +415 -0
  211. package/src/publication/__tests__/targets.integration.test.ts +120 -0
  212. package/src/publication/__tests__/video.browser.test.ts +50 -0
  213. package/src/publication/contract.ts +104 -0
  214. package/src/publication/dependencies.ts +54 -0
  215. package/src/publication/prepare-geometry.ts +94 -0
  216. package/src/publication/programs.ts +45 -0
  217. package/src/publication/publisher.ts +645 -0
  218. package/src/publication/receiver.ts +297 -0
  219. package/src/publication/resource-scope.ts +31 -0
  220. package/src/publication/targets.ts +182 -0
  221. package/src/publication/video.ts +33 -0
  222. package/src/record/__tests__/material-bg-cache.unit.test.ts +15 -1
  223. package/src/record/__tests__/prepared-runtime-material.integration.test.ts +134 -0
  224. package/src/record/__tests__/sprite-material-abi.unit.test.ts +8 -10
  225. package/src/record/__tests__/video-texture-view.unit.test.ts +9 -9
  226. package/src/record/fold-buckets.ts +8 -5
  227. package/src/record/frame-snapshot.ts +6 -6
  228. package/src/record/frame.ts +87 -28
  229. package/src/record/helpers.ts +2 -2
  230. package/src/record/main-pass-geometry.ts +21 -2
  231. package/src/record/main-pass-material.ts +37 -33
  232. package/src/record/main-pass-sprite-draws.ts +6 -152
  233. package/src/record/main-pass.ts +8 -7
  234. package/src/record/prepared-material-bindings.ts +16 -37
  235. package/src/record/render-context.ts +4 -2
  236. package/src/record/shadow-pass.ts +65 -7
  237. package/src/record/sprite-instance-buffer.ts +155 -0
  238. package/src/record/target-capture-graph.ts +258 -0
  239. package/src/record/typed-frame-graph.ts +11 -207
  240. package/src/record/view-ubo.ts +1 -1
  241. package/src/record/volume-params.ts +6 -6
  242. package/src/recovery/render-system-candidate.ts +10 -18
  243. package/src/render-contract.ts +6 -1
  244. package/src/render-system-extract-tail.ts +48 -23
  245. package/src/render-system-extract.ts +11 -2
  246. package/src/render-system-presentation.ts +2 -2
  247. package/src/render-system-projections.ts +3 -2
  248. package/src/render-system-residency.ts +2 -2
  249. package/src/render-system.ts +82 -54
  250. package/src/scene/render-scene.ts +110 -100
  251. package/src/scene/render-source.ts +90 -0
  252. package/src/scene/source-systems.ts +33 -0
  253. package/src/systems/skin-palette-allocator.ts +1 -0
  254. package/src/systems/skin-palette-types.ts +11 -0
  255. package/src/systems/transparent-dispatch.ts +2 -2
  256. package/src/systems/transparent-sort-config.ts +3 -1
  257. package/src/typed-shadow-passes.ts +36 -5
  258. package/dist/chunk-BLXGONR2.mjs.map +0 -1
  259. package/dist/chunk-ELJFJ2BU.mjs.map +0 -1
  260. package/dist/chunk-ILQ5MEZF.mjs +0 -32
  261. package/dist/chunk-ILQ5MEZF.mjs.map +0 -1
  262. package/dist/chunk-MKDIT2EM.mjs.map +0 -1
  263. package/dist/chunk-OCDLEI6I.mjs.map +0 -1
  264. package/dist/chunk-ODZWR6JQ.mjs.map +0 -1
  265. package/dist/chunk-RXZ3RGOU.mjs +0 -53
  266. package/dist/chunk-RXZ3RGOU.mjs.map +0 -1
  267. package/dist/chunk-SHFUFJ5N.mjs +0 -1781
  268. package/dist/chunk-SHFUFJ5N.mjs.map +0 -1
  269. package/dist/chunk-UI5SFODX.mjs.map +0 -1
  270. package/dist/chunk-UINHLCZA.mjs +0 -2389
  271. package/dist/chunk-UINHLCZA.mjs.map +0 -1
  272. package/dist/chunk-WEX45HKH.mjs +0 -1524
  273. package/dist/chunk-WEX45HKH.mjs.map +0 -1
@@ -0,0 +1,54 @@
1
+ import type { Handle } from '@forgeax/engine-types';
2
+ import type { ExtractedFrame, RenderableSnapshot } from '../render-system-extract';
3
+
4
+ /** One asset closure for source publication and receiver admission. */
5
+ export function publicationDependencies(
6
+ row: Pick<RenderableSnapshot, 'assetHandle' | 'materials'>,
7
+ ): Handle<string, 'shared'>[] {
8
+ const handles = new Set<Handle<string, 'shared'>>([row.assetHandle as Handle<string, 'shared'>]);
9
+ for (const material of row.materials) {
10
+ for (const handle of [
11
+ material.materialHandle,
12
+ material.baseColorTexture,
13
+ material.metallicRoughnessTexture,
14
+ material.normalTexture,
15
+ material.emissiveTexture,
16
+ material.occlusionTexture,
17
+ ]) {
18
+ if (handle) handles.add(handle as Handle<string, 'shared'>);
19
+ }
20
+ for (const handle of material.textureHandles?.values() ?? []) handles.add(handle);
21
+ for (const handle of material.samplerHandles?.values() ?? []) handles.add(handle);
22
+ }
23
+ return [...handles];
24
+ }
25
+
26
+ /** Resources selected once for the frame rather than attached to geometry. */
27
+ export function publicationFrameDependencies(
28
+ frame: Pick<
29
+ ExtractedFrame,
30
+ 'cameras' | 'auxiliaryCameras' | 'skylight' | 'skybox' | 'lights' | 'volumetricFog'
31
+ >,
32
+ ): Handle<string, 'shared'>[] {
33
+ const handles = new Set<Handle<string, 'shared'>>();
34
+ const add = (handle: number | undefined) => {
35
+ if (handle) handles.add(handle as Handle<string, 'shared'>);
36
+ };
37
+ add(frame.skylight?.equirectHandle);
38
+ add(frame.skybox?.equirectHandle);
39
+ for (const camera of [...frame.cameras, ...frame.auxiliaryCameras]) add(camera.output?.colorLut);
40
+ for (const light of frame.lights.spot) {
41
+ add(light.iesProfileHandle);
42
+ add(light.cookieHandle);
43
+ add(light.projectorHandle);
44
+ }
45
+ const fogs =
46
+ frame.volumetricFog === undefined
47
+ ? []
48
+ : [frame.volumetricFog, ...(frame.volumetricFog.additional ?? [])];
49
+ for (const fog of fogs) {
50
+ add(fog.densityHandle);
51
+ add(fog.projectorHandle);
52
+ }
53
+ return [...handles];
54
+ }
@@ -0,0 +1,94 @@
1
+ import type { AssetRegistry } from '@forgeax/engine-assets-runtime';
2
+ import type { Handle, MeshAsset } from '@forgeax/engine-types';
3
+ import { buildGpuDrivenDraws } from '../extract/gpu-driven';
4
+ import type { InstanceProjectionStore } from '../instances';
5
+ import type { extractFrames, RenderableSnapshot } from '../render-system-extract';
6
+ import type { PersistentRenderScene } from '../scene/render-scene';
7
+ import type { SkinPaletteAllocator } from '../systems/skin-palette-allocator';
8
+ import { RenderPublicationError } from './contract';
9
+ import type { PreparedRenderPublication } from './receiver';
10
+ import { renderAssetByGuid } from './resource-scope';
11
+
12
+ /** Resolve GPU ownership after source data has crossed the publication boundary. */
13
+ export function preparePublicationGeometry(
14
+ input: PreparedRenderPublication,
15
+ scene: PersistentRenderScene,
16
+ palette: SkinPaletteAllocator | null | undefined,
17
+ assets: AssetRegistry,
18
+ instances: InstanceProjectionStore,
19
+ getMaterialShaderArtifact?: NonNullable<
20
+ Parameters<typeof extractFrames>[5]
21
+ >['getMaterialShaderArtifact'],
22
+ ): PreparedRenderPublication {
23
+ const replacements = new Map<number, RenderableSnapshot>();
24
+ for (const operation of input.operations) {
25
+ if (operation.kind !== 'remove' && operation.snapshot === undefined) continue;
26
+ if (operation.kind === 'remove' || operation.snapshot?.instances === undefined)
27
+ instances.release(input.resources, operation.entityKey);
28
+ const prior = scene.compositionSlot(0, operation.entityKey)?.snapshot.skin;
29
+ const pose = operation.kind === 'remove' ? undefined : operation.snapshot?.skinPose;
30
+ if (prior !== undefined && prior.identity !== pose?.identity)
31
+ palette?.releasePersistentSlice(prior.identity);
32
+ }
33
+ for (const row of input.frame.renderables) {
34
+ const { skinPose, ...source } = row;
35
+ let skin = row.skin;
36
+ if (skinPose !== undefined) {
37
+ if (palette == null)
38
+ throw new RenderPublicationError({
39
+ reason: 'unsupported',
40
+ subject: 'skin palette allocator',
41
+ });
42
+ palette.observePersistentJoints(
43
+ skinPose.identity,
44
+ skinPose.inverseBindMatrices,
45
+ skinPose.jointWorlds,
46
+ );
47
+ skin = palette.allocatePersistentSlice(skinPose);
48
+ palette.writePersistentJointPalette(skin, skinPose.inverseBindMatrices, skinPose.jointWorlds);
49
+ }
50
+ const projected =
51
+ row.instances === undefined
52
+ ? undefined
53
+ : instances.project(input.resources, row.entityKey, row.instances.transforms);
54
+ const snapshot: RenderableSnapshot = {
55
+ ...source,
56
+ ...(skin === undefined ? {} : { skin }),
57
+ ...(projected === undefined || row.instances === undefined
58
+ ? {}
59
+ : { instances: { ...row.instances, ...projected, archVersion: 0 } }),
60
+ };
61
+ if (projected !== undefined) instances.accept(input.resources, row.entityKey, projected);
62
+ const mesh = input.resources.resolveAsset<MeshAsset>(
63
+ row.assetHandle as Handle<'MeshAsset', 'shared'>,
64
+ );
65
+ if (!mesh.ok) throw mesh.error;
66
+ const gpuDrivenDraws =
67
+ row.morph === undefined
68
+ ? buildGpuDrivenDraws({
69
+ mesh: mesh.value,
70
+ materials: row.materials,
71
+ fallbackMaterial: row.material,
72
+ baseSnapshot: snapshot,
73
+ ...(getMaterialShaderArtifact === undefined ? {} : { getMaterialShaderArtifact }),
74
+ ...(row.lods === undefined
75
+ ? {}
76
+ : {
77
+ lodMeshes: row.lods.map((lod) =>
78
+ renderAssetByGuid<MeshAsset>(input.resources, assets, lod.mesh),
79
+ ),
80
+ }),
81
+ })
82
+ : [];
83
+ replacements.set(row.entityKey, { ...snapshot, gpuDrivenDraws });
84
+ }
85
+ return {
86
+ ...input,
87
+ frame: { ...input.frame, renderables: [...replacements.values()] },
88
+ operations: input.operations.map((operation) =>
89
+ operation.kind !== 'remove' && operation.snapshot !== undefined
90
+ ? { ...operation, snapshot: replacements.get(operation.entityKey) as RenderableSnapshot }
91
+ : operation,
92
+ ),
93
+ };
94
+ }
@@ -0,0 +1,45 @@
1
+ import type { AssetRegistry } from '@forgeax/engine-assets-runtime';
2
+ import { MaterialArtifactRegistry, ShaderRegistry } from '@forgeax/engine-shader';
3
+ import { type RenderPublication, RenderPublicationError } from './contract';
4
+
5
+ /** Admit immutable producer artifacts before the full Renderer prepares their pipelines. */
6
+ export function installPublicationPrograms(
7
+ assets: AssetRegistry,
8
+ programs: RenderPublication['programs'],
9
+ ): void {
10
+ if (programs.length === 0) return;
11
+ const validation = new MaterialArtifactRegistry();
12
+ const shaders = new ShaderRegistry({ manifestUrl: undefined });
13
+ const keys = new Set<string>();
14
+ for (const row of programs) {
15
+ if (keys.has(row.key) || (row.artifact !== undefined && row.artifact.key !== row.key))
16
+ throw new RenderPublicationError({
17
+ reason: 'shape',
18
+ subject: 'duplicate or mismatched program key',
19
+ });
20
+ keys.add(row.key);
21
+ shaders.installMaterialArtifact(row.key, row.shader);
22
+ const previous = assets.shaderRegistry.findMaterialArtifact(row.key);
23
+ if (
24
+ previous.ok &&
25
+ (previous.value.source !== row.shader.source ||
26
+ JSON.stringify(previous.value.paramSchema) !== JSON.stringify(row.shader.paramSchema) ||
27
+ JSON.stringify(previous.value.receipt) !== JSON.stringify(row.shader.receipt))
28
+ ) {
29
+ throw new RenderPublicationError({
30
+ reason: 'shape',
31
+ subject: `conflicting immutable shader ${row.key}`,
32
+ });
33
+ }
34
+ if (row.artifact !== undefined) {
35
+ const existing = assets.getMaterialArtifact(row.key);
36
+ if (existing !== undefined) validation.register(existing).unwrap();
37
+ validation.register(row.artifact).unwrap();
38
+ }
39
+ }
40
+ for (const row of programs) {
41
+ if (row.artifact !== undefined) assets.materialArtifactRegistry.register(row.artifact).unwrap();
42
+ if (!assets.shaderRegistry.findMaterialArtifact(row.key).ok)
43
+ assets.shaderRegistry.installMaterialArtifact(row.key, row.shader);
44
+ }
45
+ }