@forgeax/engine-vfx-render 0.1.23 → 0.1.24

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/feature/event-resources.ts","../../render/src/errors/render.ts","../../render/src/features/prepared-graphics.ts","../src/feature/particle-resources.ts","../src/feature/stage-plan.ts","../src/feature/gpu-particle-feature.ts","../src/host/data-interface-providers.ts","../src/host/vfx-runtime-host.ts"],"names":["err","ok","failure","VFX_GPU_RUNTIME_RESOURCE_KEY"],"mappings":"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","file":"index.mjs","sourcesContent":["import type { VfxGpuEmitterProgram, VfxGpuTickIntent } from '@forgeax/engine-vfx';\n\nexport const VFX_EVENT_INPUT_BYTES = 32;\nexport const VFX_EVENT_BYTES = 32;\nexport const VFX_EVENT_COUNTER_BYTES = 16;\n\nfunction channelFanOut(emitter: VfxGpuEmitterProgram, channel: string): number {\n return Math.max(\n 1,\n ...(emitter.events ?? [])\n .filter((event) => event.channel === channel)\n .map((event) => event.fanOut),\n );\n}\n\nexport function eventInputCapacity(emitter: VfxGpuEmitterProgram): number {\n return Math.max(\n 1,\n (emitter.channels ?? []).reduce((total, channel) => total + channel.capacity, 0),\n );\n}\n\nexport function eventCapacity(emitter: VfxGpuEmitterProgram): number {\n const capacity = (emitter.channels ?? []).reduce(\n (total, channel) => total + channel.capacity * channelFanOut(emitter, channel.id),\n 0,\n );\n return Math.max(1, Math.min(emitter.capacity, capacity));\n}\n\nfunction channelKey(channel: string): number {\n let hash = 2166136261;\n for (const code of channel) {\n hash ^= code.codePointAt(0) ?? 0;\n hash = Math.imul(hash, 16777619);\n }\n return hash >>> 0;\n}\n\nexport function encodeEventInputs(intent: VfxGpuTickIntent): Uint8Array {\n const capacity = eventInputCapacity(intent.emitter);\n const data = new ArrayBuffer(capacity * VFX_EVENT_INPUT_BYTES);\n const bytes = new Uint8Array(data);\n bytes.fill(0xff);\n const view = new DataView(data);\n for (const [index, input] of intent.channelInputs.entries()) {\n if (index >= capacity) break;\n const offset = index * VFX_EVENT_INPUT_BYTES;\n view.setFloat32(offset, input.payload.position[0], true);\n view.setFloat32(offset + 4, input.payload.position[1], true);\n view.setFloat32(offset + 8, input.payload.position[2], true);\n view.setFloat32(offset + 16, input.payload.strength, true);\n view.setUint32(offset + 20, input.sequence, true);\n view.setUint32(offset + 24, channelKey(input.channel), true);\n view.setUint32(offset + 28, channelFanOut(intent.emitter, input.channel), true);\n }\n return bytes;\n}\n\nexport function eventCounterData(): Uint8Array {\n return new Uint8Array(VFX_EVENT_COUNTER_BYTES);\n}\n","// @forgeax/engine-render -- render cluster error classes.\n//\n// feat-20260704-runtime-tier1-decomposition M2 / w8 (D-3): the monolithic\n// errors.ts RuntimeErrorCode / RuntimeError top-level aggregate unions are\n// decomposed into five per-cluster files (render / asset / skin / recover /\n// environment). Each cluster owns a closed *ErrorCode code union + a closed\n// *Error class union; error class names, .code literals, and .detail shapes\n// are preserved byte-for-byte (OOS-4: zero semantic change).\n//\n// The render cluster holds the shadow / HDRP cluster-forward + deferred /\n// g-buffer / point-shadow-atlas / video-upload / vertex-storage-buffer render\n// path errors. ShadowInvalidConfigError is consumed by the DirectionalLight /\n// SpotLight / PointLightShadow component validators (forward cross-directory\n// import, no cycle -- research Finding C2).\n\nimport type {\n RenderSurfaceFailureDetail,\n SurfaceFailureCode,\n SurfaceFailureKind,\n} from '@forgeax/engine-render-graph';\nimport type { DeviceResourceKind, DeviceScopeReceipt } from '../device/resource-types';\nimport type {\n PreparedKind,\n RenderFeatureCapabilityKey,\n RenderFeatureRecovery,\n RenderFeatureStage,\n} from '../features/vocabulary';\nimport type { SceneDataLane, SceneDataSchemaId } from '../temporal/scene-data';\nimport type { TransmissionCapabilityFact } from '../transmission/backdrop';\n\nexport interface LifecycleConstructionFailureDetail {\n readonly owner: string;\n readonly generation: number;\n readonly operation: 'create' | 'dispose';\n readonly resourceKind: DeviceResourceKind;\n readonly cause: unknown;\n readonly cleanupFailures: readonly {\n readonly resourceKind: DeviceResourceKind;\n readonly cause: unknown;\n }[];\n readonly receipt: DeviceScopeReceipt;\n}\n\nexport class LifecycleConstructionError extends Error {\n readonly code = 'lifecycle-construction-failed' as const;\n readonly expected = 'all DeviceScope resources establish and terminate in order';\n readonly hint = 'inspect detail and cleanupFailures, then recover or rebuild the DeviceScope';\n readonly detail: LifecycleConstructionFailureDetail;\n\n constructor(detail: LifecycleConstructionFailureDetail) {\n super(`lifecycle-construction-failed: ${detail.resourceKind} lifecycle transaction failed`);\n this.name = 'LifecycleConstructionError';\n this.detail = detail;\n }\n}\n\nconst SURFACE_FAILURE_POLICY: Readonly<\n Record<SurfaceFailureCode, { readonly expected: string; readonly hint: string }>\n> = {\n 'surface-allocation-failed': {\n expected: 'the required surface resource can be allocated with its declared format and usage',\n hint: 'inspect the capability detail, release transient resources, and retry the candidate graph',\n },\n 'surface-attachment-failed': {\n expected: 'the float target is renderable as the declared attachment',\n hint: 'verify float color attachment support and retry without hiding the failure',\n },\n 'surface-sampled-read-failed': {\n expected: 'the float target can be sampled by the next post-processing stage',\n hint: 'verify sampled-read support for the declared format before rebuilding the graph',\n },\n 'surface-view-domain-failed': {\n expected: 'surface storage and display views preserve their declared color domains',\n hint: 'repair the explicit format/domain pair and retry the candidate graph',\n },\n 'surface-raw-endpoint-failed': {\n expected: 'the surface presentation endpoint has descriptor, acquisition, and validation proof',\n hint: 'run the concrete presentation probe; keep the last-known-good surface when proof is absent',\n },\n};\n\n/** Render-surface failure with an exhaustive code and actionable detail. */\nexport class RenderSurfaceError<\n Code extends SurfaceFailureCode = SurfaceFailureCode,\n> extends Error {\n readonly code: Code;\n readonly expected: string;\n readonly hint: string;\n readonly detail: RenderSurfaceFailureDetail;\n\n constructor(code: Code, detail: RenderSurfaceFailureDetail) {\n const policy = SURFACE_FAILURE_POLICY[code];\n if (policy === undefined) {\n throw new Error(`unknown render surface failure code: ${code}`);\n }\n super(`[RenderSurfaceError ${code}] expected: ${policy.expected}; hint: ${policy.hint}`);\n this.name = 'RenderSurfaceError';\n this.code = code;\n this.expected = policy.expected;\n this.hint = policy.hint;\n this.detail = detail;\n }\n}\n\nexport type { RenderSurfaceFailureDetail, SurfaceFailureCode, SurfaceFailureKind };\n\nexport type RenderSurfaceExpectedError = {\n readonly [Code in SurfaceFailureCode]: RenderSurfaceError<Code>;\n}[SurfaceFailureCode];\n\n/** Construct the closed surface error from its failure-stage discriminant. */\nexport function createRenderSurfaceError(\n kind: SurfaceFailureKind,\n detail: RenderSurfaceFailureDetail,\n): RenderSurfaceExpectedError {\n return new RenderSurfaceError(`surface-${kind}-failed` as SurfaceFailureCode, detail);\n}\n\nexport type LightResourceFailureReason = 'asset' | 'format' | 'capability' | 'capacity';\n\nexport interface LightResourceUnavailableDetail {\n readonly entity: number;\n readonly feature: 'ies' | 'cookie' | 'probe';\n readonly generation: number;\n readonly sourceKey: string;\n readonly reason: LightResourceFailureReason;\n}\n\nexport class LightResourceUnavailableError extends Error {\n readonly code = 'light-resource-unavailable' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: LightResourceUnavailableDetail;\n\n constructor(\n detail: LightResourceUnavailableDetail,\n expected: string,\n actual: string,\n hint: string,\n ) {\n super(`light-resource-unavailable: ${detail.feature} ${actual}`);\n this.name = 'LightResourceUnavailableError';\n this.expected = expected;\n this.hint = hint;\n this.detail = detail;\n }\n}\n\nexport function createLightResourceUnavailable(input: {\n readonly entity: number;\n readonly feature: LightResourceUnavailableDetail['feature'];\n readonly generation: number;\n readonly sourceKey: string;\n readonly reason: LightResourceFailureReason;\n readonly expected: string;\n readonly actual: string;\n readonly hint: string;\n}): LightResourceUnavailableError {\n return new LightResourceUnavailableError(\n {\n entity: input.entity,\n feature: input.feature,\n generation: input.generation,\n sourceKey: input.sourceKey,\n reason: input.reason,\n },\n input.expected,\n input.actual,\n input.hint,\n );\n}\n\nexport interface TemporalFrameSubmitDetail {\n readonly reason: 'queue-submit-failed';\n}\n\nexport class TemporalFrameSubmitError extends Error {\n readonly code = 'temporal-frame-submit-rejected' as const;\n readonly expected = 'the staged frame is accepted by queue.submit before temporal facts advance';\n readonly hint = 'inspect the queue submission and retry the frame after the device is available';\n readonly detail: TemporalFrameSubmitDetail;\n\n constructor(reason: 'queue-submit-failed') {\n super(`temporal-frame-submit-rejected: ${reason}`);\n this.name = 'TemporalFrameSubmitError';\n this.detail = { reason };\n }\n}\n// ── ShadowInvalidConfigError ──────────────────────────────────────────────\n\n/**\n * Detail for `RuntimeErrorCode 'shadow-invalid-config'`.\n *\n * The four fields are the only recovery surface: AI users read the invalid\n * field, actual value, structured bound, and reason without parsing prose.\n */\nexport type ShadowInvalidConfigBound =\n | { readonly kind: 'range'; readonly min: number; readonly max: number }\n | { readonly kind: 'lower-bound'; readonly operator: '>' | '>='; readonly value: number }\n | { readonly kind: 'allowed-values'; readonly values: readonly number[] };\n\nexport interface ShadowInvalidConfigDetail {\n readonly field: string;\n readonly actual: number;\n readonly bound: ShadowInvalidConfigBound;\n readonly reason: string;\n}\n\n/**\n * Structured error for shadow component config validation failures.\n *\n * Emitted by Directional, Point, and Spot shadow validation. All three\n * component owners share this error class so `switch (err.code)` on\n * `RuntimeErrorCode` needs one branch (charter P4 — closed-union SSOT).\n * Four-field surface:\n * - `.code = 'shadow-invalid-config'` (closed RuntimeErrorCode)\n * - `.expected` — expected-state description (programmatic predicate form)\n * - `.hint` — actionable recovery guidance (imperative; AI users paste into\n * spawn calls).\n * - `.detail = { field, actual, bound, reason }` — structured values.\n */\nexport class ShadowInvalidConfigError extends Error {\n readonly code = 'shadow-invalid-config' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: ShadowInvalidConfigDetail;\n\n constructor(\n field: string,\n actual: number,\n minOrBound: number | ShadowInvalidConfigBound,\n maxOrComparator?: number | '>' | '>=',\n reason?: string,\n ) {\n const bound: ShadowInvalidConfigBound =\n typeof minOrBound === 'number'\n ? typeof maxOrComparator === 'number'\n ? { kind: 'range', min: minOrBound, max: maxOrComparator }\n : {\n kind: 'lower-bound',\n operator: maxOrComparator === '>' ? '>' : '>=',\n value: minOrBound,\n }\n : minOrBound;\n const resolvedReason = reason ?? shadowBoundReason(bound);\n const expected = shadowBoundExpected(field, bound);\n const hint = `set ${field} to ${resolvedReason}; got ${actual}`;\n super(`shadow component .${field} is invalid: ${resolvedReason}; got ${actual}`);\n this.name = 'ShadowInvalidConfigError';\n this.hint = hint;\n this.expected = expected;\n this.detail = { field, actual, bound, reason: resolvedReason };\n }\n}\n\nfunction shadowBoundExpected(field: string, bound: ShadowInvalidConfigBound): string {\n switch (bound.kind) {\n case 'range':\n return `${field} in [${bound.min}, ${bound.max}]`;\n case 'lower-bound':\n return `${field} ${bound.operator} ${bound.value}`;\n case 'allowed-values':\n return `${field} in {${bound.values.join(', ')}}`;\n }\n}\n\nfunction shadowBoundReason(bound: ShadowInvalidConfigBound): string {\n switch (bound.kind) {\n case 'range':\n return `a value in [${bound.min}, ${bound.max}]`;\n case 'lower-bound':\n return `a value ${bound.operator} ${bound.value}`;\n case 'allowed-values':\n return `one of [${bound.values.join(', ')}]`;\n }\n}\n\n// ── EquirectProjectionFailedError ────────────────────────────────────────────\n\n/**\n * Detail for `RuntimeErrorCode 'equirect-projection-failed'`.\n *\n * Emitted when the equirect-to-cubemap IBL projection fails for the equirect\n * handle referenced by a `Skylight` / `SkyboxBackground` component. The handle\n * id is carried so AI users can trace which equirect source failed projection.\n * Degradation: the record arm records `status:'failed'`, binds the white-cube\n * fallback, fires this error ONCE, and does NOT retry the projection.\n *\n * feat-20260630 D-5: structured error with detail carrying the handle id.\n */\nexport interface EquirectProjectionFailedDetail {\n readonly handle: number;\n}\n\n/**\n * Structured error for a failed equirect-to-cubemap IBL projection.\n *\n * Emitted by the record stage when the internal cubemap projection for an\n * equirect handle returns a failure (or records `status:'failed'`). Four-field\n * surface per AGENTS.md error model:\n * - `.code = 'equirect-projection-failed'` (closed RuntimeErrorCode)\n * - `.expected` — equirect-to-cubemap projection + IBL precompute succeeds\n * - `.hint` — declare `Skylight{equirect}` with a valid HDR equirect source;\n * check `device.caps.rgba16floatRenderable`. The projection is internal —\n * there is no user upload call to retry\n * - `.detail = { handle }` — the numeric equirect handle id for diagnostics\n */\nexport class EquirectProjectionFailedError extends Error {\n readonly code = 'equirect-projection-failed' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: EquirectProjectionFailedDetail;\n\n constructor(handle: number) {\n const expected = `equirect handle ${handle} projects to a GPU cubemap + IBL precompute`;\n const hint =\n `equirect handle ${handle} referenced by Skylight/SkyboxBackground failed projection; ` +\n `declare Skylight{equirect} with a valid HDR equirect source and check device.caps.rgba16floatRenderable. ` +\n `The projection is internal (no user upload call); the record arm does not retry`;\n super(`equirect handle ${handle} cubemap projection failed`);\n this.name = 'EquirectProjectionFailedError';\n this.expected = expected;\n this.hint = hint;\n this.detail = { handle };\n }\n}\n\n// ── StandardLightBudgetExceededError ──────────────────────────────────────\n\n/** The finite local-light budget that a Standard frame agreed to admit. */\nexport interface StandardLightBudgetExceededDetail {\n readonly actual: number;\n readonly budget: number;\n}\n\n/**\n * Structured refusal for a Standard frame whose finite local-light set is\n * outside the selected profile budget. The frame is rejected as a whole; the\n * record owner must not slice the input or submit a partial membership set.\n */\nexport class StandardLightBudgetExceededError extends Error {\n readonly code = 'standard-light-budget-exceeded' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: StandardLightBudgetExceededDetail;\n\n constructor(actual: number, budget: number) {\n const expected = `light count <= ${budget}`;\n const hint =\n `${actual} finite local lights exceed Standard budget ${budget}; ` +\n 'reduce the local-light set or select a profile with a supported budget';\n super(`Standard light budget exceeded: ${actual} > ${budget}`);\n this.name = 'StandardLightBudgetExceededError';\n this.expected = expected;\n this.hint = hint;\n this.detail = { actual, budget };\n }\n}\n\n// ── StandardClusterIndexOverflowError ──────────────────────────────────────\n\n/** Cluster membership entries that could not fit the single shared index list. */\nexport interface StandardClusterIndexOverflowDetail {\n readonly actual: number;\n readonly capacity: number;\n}\n\n/**\n * Structured refusal for a membership producer that exceeded the shared\n * Cluster index-list capacity. No truncated list is uploaded and no graph is\n * submitted for the rejected frame.\n */\nexport class StandardClusterIndexOverflowError extends Error {\n readonly code = 'standard-cluster-index-overflow' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: StandardClusterIndexOverflowDetail;\n\n constructor(actual: number, capacity: number) {\n const expected = `light index list entries <= ${capacity}`;\n const hint =\n `cluster binner overflow: writeCount ${actual} exceeds capacity ${capacity}; ` +\n 'reduce finite local lights or choose a supported cluster layout';\n super(`Standard cluster index list overflow: ${actual} > ${capacity}`);\n this.name = 'StandardClusterIndexOverflowError';\n this.expected = expected;\n this.hint = hint;\n this.detail = { actual, capacity };\n }\n}\n\n// ── StandardClusterTransportUnavailableError ───────────────────────────────\n\nexport interface StandardClusterTransportUnavailableDetail {\n readonly requested: number;\n readonly admitted: 0;\n}\n\n/**\n * Structured capability refusal. Standard never turns an unproven transport\n * into a smaller direct-light lane; the caller receives the exact requested\n * local-light count and an admitted count of zero.\n */\nexport class StandardClusterTransportUnavailableError extends Error {\n readonly code = 'standard-cluster-transport-unavailable' as const;\n readonly expected = 'all requested local lights have a proven Cluster transport';\n readonly hint: string;\n readonly detail: StandardClusterTransportUnavailableDetail;\n\n constructor(\n requested: number,\n hint = 'enable a proven Cluster storage transport before drawing',\n ) {\n super(`Standard Cluster transport unavailable for ${requested} local lights`);\n this.name = 'StandardClusterTransportUnavailableError';\n this.hint = hint;\n this.detail = { requested, admitted: 0 };\n }\n}\n\n// ── StandardProfileInvalidError ───────────────────────────────────────────\n\nexport interface StandardProfileInvalidDetail {\n readonly field: string;\n readonly actual: unknown;\n}\n\n/** Structured validation failure for the single Standard profile surface. */\nexport class StandardProfileInvalidError extends Error {\n readonly code = 'standard-profile-invalid' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: StandardProfileInvalidDetail;\n\n constructor(message: string, detail?: StandardProfileInvalidDetail) {\n super(message);\n this.name = 'StandardProfileInvalidError';\n this.detail = detail ?? { field: 'profile', actual: message };\n if (this.detail.field === 'clusterGrid') {\n this.expected = 'clusterGrid.{x,y,z} each positive integer in [1, 64]';\n this.hint =\n 'set clusterGrid.x, clusterGrid.y, and clusterGrid.z to positive integers in [1, 64]';\n } else {\n this.expected = 'StandardProfile contains only supported fields and values';\n this.hint = 'repair the Standard profile fields and retry setProfile';\n }\n }\n}\n\n// ── PointShadowAtlasUninitializedError ─────────────────────────────────────\n\n/**\n * Structured error for `ShadowAtlas.faceView` called before `ensure()`\n * allocated the cube_array texture. Replaces the prior bare\n * `throw new Error()` (Round-2 F-4: P3 closed-union compliance).\n *\n * - `.code = 'point-shadow-atlas-uninitialized'`\n * - `.expected` — call `ensure()` before iterating face views\n * - `.hint` — gate `faceView` on `isAllocated()` or call `ensure()` once\n * in the per-frame extract step before recording the 6 x N caster passes\n * - `.detail = undefined` (no per-call data needed)\n */\nexport class PointShadowAtlasUninitializedError extends Error {\n readonly code = 'point-shadow-atlas-uninitialized' as const;\n readonly expected: string;\n readonly hint: string;\n\n constructor() {\n const expected = 'ShadowAtlas.ensure() invoked before faceView()';\n const hint =\n 'Gate faceView on isAllocated() or call ensure() once in the per-frame extract step before iterating face views';\n super('ShadowAtlas.faceView called before ensure(); the cube_array texture is not allocated');\n this.name = 'PointShadowAtlasUninitializedError';\n this.expected = expected;\n this.hint = hint;\n }\n}\n\n// ── PointShadowAtlasBoundsViolationError ───────────────────────────────────\n\n/**\n * Detail for `RuntimeErrorCode 'point-shadow-atlas-bounds-violation'`.\n *\n * Emitted by `ShadowAtlas.faceView` when `layer` falls outside `[0, layers)`\n * or `face` falls outside `[0, 6)`. Both axes are reported as\n * `{ axis, value, max }` so AI users discriminate without parsing the message.\n */\nexport interface PointShadowAtlasBoundsViolationDetail {\n readonly axis: 'layer' | 'face';\n readonly value: number;\n readonly max: number;\n}\n\n/**\n * Structured error for `ShadowAtlas.faceView(layer, face)` arguments outside\n * the allocated atlas range. Replaces the prior bare `throw new Error()`\n * (Round-2 F-4: P3 closed-union compliance).\n *\n * - `.code = 'point-shadow-atlas-bounds-violation'`\n * - `.expected` — `0 <= layer < layers && 0 <= face < 6`\n * - `.hint` — clamp `shadowAtlasLayer` or face index before calling\n * `faceView`; the layer cap is the renderer-owned ShadowAtlas capacity\n * - `.detail = { axis, value, max }` — discriminates layer vs face\n */\nexport class PointShadowAtlasBoundsViolationError extends Error {\n readonly code = 'point-shadow-atlas-bounds-violation' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: PointShadowAtlasBoundsViolationDetail;\n\n constructor(axis: 'layer' | 'face', value: number, max: number) {\n const expected = `0 <= ${axis} < ${max}`;\n const hint =\n axis === 'layer'\n ? `clamp PointLight.shadowAtlasLayer to [0, ${max}); the cap on layers equals PointLightShadow cardinality (4)`\n : `clamp face index to [0, ${max}); cube faces are indexed 0..5 in +X/-X/+Y/-Y/+Z/-Z order`;\n super(`ShadowAtlas.faceView ${axis} out of range: ${value} (must be in [0, ${max}))`);\n this.name = 'PointShadowAtlasBoundsViolationError';\n this.expected = expected;\n this.hint = hint;\n this.detail = { axis, value, max };\n }\n}\n\n// ── VideoUploadUnsupportedError ─────────────────────────────────────────\n\n/**\n * Structured error for `RuntimeErrorCode 'video-upload-unsupported'`\n * (feat-20260623-world-space-video-asset M3 / w11 — AC-10).\n *\n * Fired by the per-frame record stage (`videoTextureView`) when a VideoPlayer\n * entity can reach neither video upload path this frame: the general\n * `copyExternalImageToTexture` path (no host HTMLVideoElement resolved via\n * `VideoElementProvider`) AND the high-perf `GPUExternalTexture` path\n * (capability absent). The engine surfaces this explicit failure rather than\n * silently rendering a stale/garbage texture (charter P3, plan-strategy D-6).\n * - `.code = 'video-upload-unsupported'`\n * - `.expected` — at least one upload path available (host element or\n * GPUExternalTexture capability)\n * - `.hint` — actionable recovery: use a static texture or switch backend\n * - `.detail` — undefined (no narrowed detail variant)\n */\nexport class VideoUploadUnsupportedError extends Error {\n readonly code = 'video-upload-unsupported' as const;\n readonly expected: string;\n readonly hint: string;\n\n constructor() {\n const expected =\n 'at least one video upload path available: a host HTMLVideoElement (general copyExternalImageToTexture path) or GPUExternalTexture capability (high-perf path)';\n const hint =\n 'this backend exposes no usable video upload path; render a static texture instead, or switch to a WebGPU backend that supports video texture upload';\n super('video upload unsupported — no general or high-perf path available');\n this.name = 'VideoUploadUnsupportedError';\n this.expected = expected;\n this.hint = hint;\n }\n}\n\n// ── VertexStorageBufferUnavailableError ─────────────────────────────────\n\n/**\n * Structured error for missing vertex-stage storage buffer capability.\n *\n * Emitted at createRenderer time (cap-gate).\n * - `.code = 'vertex-storage-buffer-unavailable'`\n * - `.expected` — device.caps supports vertex-stage storage buffer\n * - `.hint` — switch to a WebGPU adapter with vertex storage buffer support or use uniform-buffer fallback (OOS-uniform-palette)\n * - `.detail` — undefined (no narrowed detail variant)\n */\nexport class VertexStorageBufferUnavailableError extends Error {\n readonly code = 'vertex-storage-buffer-unavailable' as const;\n readonly expected: string;\n readonly hint: string;\n\n constructor() {\n const expected =\n 'device.caps supports vertex-stage storage buffer (maxStorageBuffersPerShaderStage >= 1)';\n const hint =\n 'this device does not support vertex-stage storage buffers; skinning requires vertex-stage storage buffer access (OOS-uniform-palette fallback not implemented)';\n super('vertex-stage storage buffer unavailable — skinning cannot operate');\n this.name = 'VertexStorageBufferUnavailableError';\n this.expected = expected;\n this.hint = hint;\n }\n}\n\n// ── VertexColorVariantConflictError ───────────────────────────────────────\n\nexport interface VertexColorVariantConflictDetail {\n readonly authored: true;\n readonly authoredValue: string;\n readonly projected: boolean;\n}\n\n/** The authored color axis disagrees with the canonical geometry projection. */\nexport class VertexColorVariantConflictError extends Error {\n readonly code = 'vertex-color-variant-conflict' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: VertexColorVariantConflictDetail;\n\n constructor(authoredValue: string, projected: boolean) {\n const expected = `VERTEX_COLOR_AVAILABLE=${projected ? 'true' : 'false'}`;\n const hint =\n 'derive the shader variant from the mesh VertexLayoutProjection; COLOR_0 presence is a geometry fact';\n super(`authored vertex-color variant ${authoredValue} disagrees with projected ${expected}`);\n this.name = 'VertexColorVariantConflictError';\n this.expected = expected;\n this.hint = hint;\n this.detail = { authored: true, authoredValue, projected };\n }\n}\n\n// ── Skin palette/material validation errors ────────────────────────────────\n\n/** Detail for a palette buffer that exceeds the device storage limit. */\nexport interface SkinPaletteOverflowDetail {\n readonly requestedBytes: number;\n readonly limit: number;\n}\n\n/**\n * Structured render error for a skin palette allocation that exceeds the\n * device storage-buffer binding limit. The allocator that emits this error\n * lives in render, so the error belongs to the render union rather than the\n * renderer-independent skinning binding package.\n */\nexport class SkinPaletteOverflowError extends Error {\n readonly code = 'skin-palette-overflow' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: SkinPaletteOverflowDetail;\n\n constructor(requestedBytes: number, limit: number) {\n const expected = `skinned joint palette (${requestedBytes} B) fits within device.limits.maxStorageBufferBindingSize (${limit} B)`;\n const hint =\n 'palette buffer exceeds device maxStorageBufferBindingSize; reduce skinned entity count or split into multiple palette buffers (OOS-skin-palette-batch)';\n super(`skin palette buffer needs ${requestedBytes} B, exceeds device limit ${limit} B`);\n this.name = 'SkinPaletteOverflowError';\n this.expected = expected;\n this.hint = hint;\n this.detail = { requestedBytes, limit };\n }\n}\n\n/** Detail for a skinned entity using a non-skin material shader. */\nexport interface SkinMaterialMismatchDetail {\n readonly entity: number;\n readonly actualShader: string | undefined;\n}\n\n/** Structured render error for a Skin/non-skin-material mismatch. */\nexport class SkinMaterialMismatchError extends Error {\n readonly code = 'skin-material-mismatch' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: SkinMaterialMismatchDetail;\n\n constructor(entity: number, actualShader: string | undefined) {\n const expected = \"Skin entity's first material program module === 'forgeax::pbr-skin'\";\n const hint = `entity ${entity} has Skin but the first material program module is ${actualShader ?? '<empty>'}; load the mesh via the gltf importer (cooker auto-routes 'forgeax::pbr-skin' for skinned primitives), or remove the Skin component to render the entity unskinned with Materials.standard / Materials.unlit`;\n super(\n `Skin / material mismatch on entity ${entity}: expected forgeax::pbr-skin, got ${actualShader ?? '<empty>'}`,\n );\n this.name = 'SkinMaterialMismatchError';\n this.expected = expected;\n this.hint = hint;\n this.detail = { entity, actualShader };\n }\n}\n\n/** Detail for a pbr-skin material whose mesh lacks skin attributes. */\nexport interface MaterialSkinAttrMissingDetail {\n readonly entity: number;\n readonly missing: 'skinIndex' | 'skinWeight' | 'both';\n}\n\n/** Structured render error for a pbr-skin material/mesh attribute mismatch. */\nexport class MaterialSkinAttrMissingError extends Error {\n readonly code = 'material-skin-attr-missing' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: MaterialSkinAttrMissingDetail;\n\n constructor(entity: number, missing: 'skinIndex' | 'skinWeight' | 'both') {\n const expected = 'pbr-skin material requires mesh.attributes.skinIndex + skinWeight';\n const hint = `entity ${entity} uses forgeax::pbr-skin but its MeshAsset is missing ${missing}; switch the entity to a skinned glTF mesh authored with JOINTS_0 + WEIGHTS_0, or change the material to a non-skin shader via Materials.standard / Materials.unlit`;\n super(\n `material/skin attribute mismatch on entity ${entity}: pbr-skin material with mesh missing ${missing}`,\n );\n this.name = 'MaterialSkinAttrMissingError';\n this.expected = expected;\n this.hint = hint;\n this.detail = { entity, missing };\n }\n}\n\nexport interface TransmissionCapabilityMissingDetail {\n readonly material: string;\n readonly capability: 'transmission';\n readonly stage: 'prepare' | 'record';\n readonly lane: 'standard-forward';\n readonly format: string;\n readonly missing: readonly TransmissionCapabilityFact[];\n}\n\nexport class TransmissionCapabilityMissingError extends Error {\n readonly code = 'transmission-capability-missing' as const;\n readonly expected = 'the renderer exposes the transmission capability for this material';\n readonly hint = 'disable transmission or provide the renderer capability before drawing';\n readonly detail: TransmissionCapabilityMissingDetail;\n\n constructor(\n material: string,\n stage: 'prepare' | 'record',\n evidence: {\n readonly lane: 'standard-forward';\n readonly format: string;\n readonly missing: readonly TransmissionCapabilityFact[];\n },\n ) {\n super(`transmission capability is missing for material '${material}'`);\n this.name = 'TransmissionCapabilityMissingError';\n this.detail = { material, capability: 'transmission', stage, ...evidence };\n }\n}\n\n// -- RenderFeature errors ---------------------------------------------------\n\nexport type RenderFeatureErrorCode =\n | 'render-feature-registration-conflict'\n | 'render-feature-stage-failed'\n | 'render-feature-capability-missing'\n | 'render-feature-pass-order-conflict'\n | 'render-feature-preparation-failed'\n | 'render-feature-prepared-state-mismatch'\n | 'render-feature-draw-recording-failed';\n\nexport interface RenderFeatureRegistrationConflictDetail {\n readonly featureIdentity: string;\n readonly order: number;\n readonly conflictingOrder: number;\n}\n\nexport interface RenderFeatureCleanupFailure {\n readonly featureIdentity: string;\n readonly order: number;\n readonly code: string;\n}\n\nexport interface RenderFeatureStageFailedDetail {\n readonly featureIdentity: string;\n readonly order: number;\n readonly stage: RenderFeatureStage;\n readonly recovery: RenderFeatureRecovery;\n readonly cleanupFailures?: readonly RenderFeatureCleanupFailure[];\n}\n\nexport interface RenderFeatureCapabilityMissingDetail {\n readonly featureIdentity: string;\n readonly order: number;\n readonly capability: RenderFeatureCapabilityKey;\n}\n\nexport interface RenderFeaturePassOrderConflictDetail {\n readonly featureIdentity: string;\n readonly order: number;\n readonly passIdentity: string;\n readonly dependencyIdentity: string;\n}\n\nexport interface RenderFeaturePreparationFailedDetail {\n readonly featureIdentity: string;\n readonly order: number;\n readonly stage: 'prepare';\n readonly operation: string;\n readonly resourceKind: PreparedKind;\n readonly resourceName: string;\n readonly reason: string;\n readonly recovery: RenderFeatureRecovery;\n}\n\nexport type RenderFeaturePreparedStateMismatchDetail =\n | {\n readonly featureIdentity: string;\n readonly order: number;\n readonly stage: 'contribute';\n readonly operation: string;\n readonly resourceKind: PreparedKind;\n readonly reason: 'missing-prepared-state';\n readonly missingResource: string;\n readonly recovery: RenderFeatureRecovery;\n }\n | {\n readonly featureIdentity: string;\n readonly order: number;\n readonly stage: 'contribute';\n readonly operation: string;\n readonly resourceKind: PreparedKind;\n readonly reason: 'foreign-feature';\n readonly expectedFeatureIdentity: string;\n readonly actualFeatureIdentity: string;\n readonly recovery: RenderFeatureRecovery;\n }\n | {\n readonly featureIdentity: string;\n readonly order: number;\n readonly stage: 'contribute';\n readonly operation: string;\n readonly resourceKind: PreparedKind;\n readonly reason: 'foreign-kind';\n readonly expectedKind: PreparedKind;\n readonly actualKind: PreparedKind;\n readonly recovery: RenderFeatureRecovery;\n }\n | {\n readonly featureIdentity: string;\n readonly order: number;\n readonly stage: 'contribute';\n readonly operation: string;\n readonly resourceKind: PreparedKind;\n readonly reason: 'generation-mismatch';\n readonly expectedGeneration: number;\n readonly actualGeneration: number;\n readonly recovery: RenderFeatureRecovery;\n }\n | {\n readonly featureIdentity: string;\n readonly order: number;\n readonly stage: 'contribute';\n readonly operation: string;\n readonly resourceKind: PreparedKind;\n readonly reason: 'layout-mismatch';\n readonly expectedLayout: string;\n readonly actualLayout: string;\n readonly recovery: RenderFeatureRecovery;\n }\n | {\n readonly featureIdentity: string;\n readonly order: number;\n readonly stage: 'contribute';\n readonly operation: string;\n readonly resourceKind: PreparedKind;\n readonly reason: 'format-mismatch';\n readonly expectedFormat: string;\n readonly actualFormat: string;\n readonly recovery: RenderFeatureRecovery;\n };\n\nexport interface RenderFeatureDrawRecordingFailedDetail {\n readonly featureIdentity: string;\n readonly order: number;\n readonly stage: 'record';\n readonly operation: string;\n readonly resourceKind: PreparedKind;\n readonly reason: string;\n readonly backendReason: string;\n readonly recovery: RenderFeatureRecovery;\n}\n\nexport type RenderFeatureErrorDetailByCode = {\n 'render-feature-registration-conflict': RenderFeatureRegistrationConflictDetail;\n 'render-feature-stage-failed': RenderFeatureStageFailedDetail;\n 'render-feature-capability-missing': RenderFeatureCapabilityMissingDetail;\n 'render-feature-pass-order-conflict': RenderFeaturePassOrderConflictDetail;\n 'render-feature-preparation-failed': RenderFeaturePreparationFailedDetail;\n 'render-feature-prepared-state-mismatch': RenderFeaturePreparedStateMismatchDetail;\n 'render-feature-draw-recording-failed': RenderFeatureDrawRecordingFailedDetail;\n};\n\n/** Machine-readable four-field diagnostic exposed by every feature error. */\nexport type RenderFeatureErrorDescriptor = {\n [Code in RenderFeatureErrorCode]: {\n readonly code: Code;\n readonly expected: string;\n readonly hint: string;\n readonly detail: RenderFeatureErrorDetailByCode[Code];\n };\n}[RenderFeatureErrorCode];\n\nconst renderFeatureRecoveryHintByRecovery = {\n 'next-frame': (featureIdentity: string, stage: RenderFeatureStage) =>\n `correct '${featureIdentity}' ${stage} data and retry on the next frame`,\n 'renderer-recover': (featureIdentity: string, _stage: RenderFeatureStage) =>\n `wait for renderer recovery before retrying '${featureIdentity}'`,\n registration: (featureIdentity: string, _stage: RenderFeatureStage) =>\n `correct '${featureIdentity}' registration before retrying`,\n} satisfies Record<\n RenderFeatureRecovery,\n (featureIdentity: string, stage: RenderFeatureStage) => string\n>;\n\nexport class RenderFeatureRegistrationConflictError extends Error {\n readonly code = 'render-feature-registration-conflict' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: RenderFeatureRegistrationConflictDetail;\n\n constructor(featureIdentity: string, order: number, conflictingOrder: number) {\n const expected = `feature identity '${featureIdentity}' is unique`;\n const hint = `rename '${featureIdentity}' or remove the duplicate feature before registration`;\n super(`render feature registration conflict for '${featureIdentity}'`);\n this.name = 'RenderFeatureRegistrationConflictError';\n this.expected = expected;\n this.hint = hint;\n this.detail = { featureIdentity, order, conflictingOrder };\n }\n}\n\nexport class RenderFeatureStageFailedError extends Error {\n readonly code = 'render-feature-stage-failed' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: RenderFeatureStageFailedDetail;\n\n constructor(\n featureIdentity: string,\n order: number,\n stage: RenderFeatureStage,\n recovery: RenderFeatureRecovery,\n ) {\n const expected = `feature '${featureIdentity}' completes its ${stage} stage without an error`;\n const hint = renderFeatureRecoveryHintByRecovery[recovery](featureIdentity, stage);\n super(`render feature '${featureIdentity}' failed during ${stage}`);\n this.name = 'RenderFeatureStageFailedError';\n this.expected = expected;\n this.hint = hint;\n this.detail = { featureIdentity, order, stage, recovery };\n }\n}\n\nexport class RenderFeatureCapabilityMissingError extends Error {\n readonly code = 'render-feature-capability-missing' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: RenderFeatureCapabilityMissingDetail;\n\n constructor(\n featureIdentity: string,\n order: number,\n capability: RenderFeatureCapabilityMissingDetail['capability'],\n ) {\n const expected = `device capability '${capability}' is available for feature '${featureIdentity}'`;\n const hint = `disable '${featureIdentity}' or use a device with '${capability}' capability`;\n super(`render feature '${featureIdentity}' requires missing capability '${capability}'`);\n this.name = 'RenderFeatureCapabilityMissingError';\n this.expected = expected;\n this.hint = hint;\n this.detail = { featureIdentity, order, capability };\n }\n}\n\nexport class RenderFeaturePassOrderConflictError extends Error {\n readonly code = 'render-feature-pass-order-conflict' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: RenderFeaturePassOrderConflictDetail;\n\n constructor(\n featureIdentity: string,\n order: number,\n passIdentity: string,\n dependencyIdentity: string,\n ) {\n const expected = `feature pass '${passIdentity}' follows dependency '${dependencyIdentity}'`;\n const hint = `reorder '${featureIdentity}' passes so '${passIdentity}' follows '${dependencyIdentity}'`;\n super(`render feature '${featureIdentity}' pass order conflict`);\n this.name = 'RenderFeaturePassOrderConflictError';\n this.expected = expected;\n this.hint = hint;\n this.detail = { featureIdentity, order, passIdentity, dependencyIdentity };\n }\n}\n\nexport class RenderFeaturePreparationFailedError extends Error {\n readonly code = 'render-feature-preparation-failed' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: RenderFeaturePreparationFailedDetail;\n\n constructor(\n featureIdentity: string,\n order: number,\n operation: string,\n resourceKind: RenderFeaturePreparationFailedDetail['resourceKind'],\n resourceName: string,\n reason: string,\n recovery: RenderFeatureRecovery,\n ) {\n const expected = `${resourceKind} '${resourceName}' is prepared during ${operation}`;\n const hint = `repair '${resourceName}' and retry feature '${featureIdentity}' on ${recovery}`;\n super(`render feature '${featureIdentity}' preparation failed for '${resourceName}'`);\n this.name = 'RenderFeaturePreparationFailedError';\n this.expected = expected;\n this.hint = hint;\n this.detail = {\n featureIdentity,\n order,\n stage: 'prepare',\n operation,\n resourceKind,\n resourceName,\n reason,\n recovery,\n };\n }\n}\n\nexport class RenderFeaturePreparedStateMismatchError extends Error {\n readonly code = 'render-feature-prepared-state-mismatch' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: RenderFeaturePreparedStateMismatchDetail;\n\n constructor(detail: RenderFeaturePreparedStateMismatchDetail) {\n const expected = `${detail.resourceKind} state is compatible for '${detail.operation}'`;\n const hint = `repair '${detail.reason}' for feature '${detail.featureIdentity}' and retry`;\n super(`render feature '${detail.featureIdentity}' prepared state mismatch`);\n this.name = 'RenderFeaturePreparedStateMismatchError';\n this.expected = expected;\n this.hint = hint;\n this.detail = detail;\n }\n}\n\nexport class RenderFeatureDrawRecordingFailedError extends Error {\n readonly code = 'render-feature-draw-recording-failed' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: RenderFeatureDrawRecordingFailedDetail;\n\n constructor(\n featureIdentity: string,\n order: number,\n operation: string,\n resourceKind: RenderFeatureDrawRecordingFailedDetail['resourceKind'],\n reason: string,\n backendReason: string,\n recovery: RenderFeatureRecovery,\n ) {\n const expected = `${resourceKind} recording succeeds for '${operation}'`;\n const hint = `repair '${reason}' and retry feature '${featureIdentity}' after ${recovery}`;\n super(`render feature '${featureIdentity}' draw recording failed`);\n this.name = 'RenderFeatureDrawRecordingFailedError';\n this.expected = expected;\n this.hint = hint;\n this.detail = {\n featureIdentity,\n order,\n stage: 'record',\n operation,\n resourceKind,\n reason,\n backendReason,\n recovery,\n };\n }\n}\n\n// ── ObservationUnavailableError ───────────────────────────────────────────\n\nexport type ObservationUnavailableReason =\n | 'no-frame'\n | 'resource'\n | 'copy-src'\n | 'stale'\n | 'identity'\n | 'format'\n | 'readback-failed';\n\nexport interface ObservationUnavailableDetail {\n readonly reason: ObservationUnavailableReason;\n readonly recovery: 'draw-current-frame' | 'enable-copy-src' | 'retry-readback';\n}\n\n/** A producer-owned current-frame observation could not be made available. */\nexport class ObservationUnavailableError extends Error {\n readonly code = 'observation-unavailable' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: ObservationUnavailableDetail;\n\n constructor(reason: ObservationUnavailableReason, hint: string) {\n let recovery: ObservationUnavailableDetail['recovery'];\n if (reason === 'copy-src') recovery = 'enable-copy-src';\n else if (reason === 'resource' || reason === 'readback-failed') recovery = 'retry-readback';\n else recovery = 'draw-current-frame';\n super(`current-frame observation unavailable: ${reason}`);\n this.name = 'ObservationUnavailableError';\n this.expected = 'a fresh producer-owned rgba16float current-frame observation';\n this.hint = hint;\n this.detail = { reason, recovery };\n }\n}\n\nexport type SceneDataUnavailableReason =\n | 'capability-missing'\n | 'producer-missing'\n | 'coverage-incomplete'\n | 'renderer-recovering';\nexport interface SceneDataUnavailableDetail {\n readonly featureIdentity: string;\n readonly schema: SceneDataSchemaId;\n readonly lane: SceneDataLane;\n readonly reason: SceneDataUnavailableReason;\n readonly missingContributorIds: readonly string[];\n readonly omittedMissingContributorCount: number;\n readonly recovery: 'enable-capability' | 'next-frame' | 'renderer-recover';\n}\nexport class SceneDataUnavailableError extends Error {\n readonly code = 'scene-data-unavailable' as const;\n readonly expected = 'the requested semantic scene data is available for the active plan';\n readonly hint: string;\n readonly detail: SceneDataUnavailableDetail;\n constructor(detail: SceneDataUnavailableDetail) {\n const hint =\n detail.recovery === 'enable-capability'\n ? 'enable rgba16floatRenderable and retry the current frame'\n : detail.recovery === 'renderer-recover'\n ? 'wait for renderer recovery, then retry the frame'\n : 'restore the producer coverage and retry on the next frame';\n super(`scene data '${detail.schema}' unavailable for '${detail.featureIdentity}'`);\n this.name = 'SceneDataUnavailableError';\n this.hint = hint;\n this.detail = Object.freeze({\n ...detail,\n missingContributorIds: Object.freeze([...detail.missingContributorIds].slice(0, 32)),\n omittedMissingContributorCount: Math.max(\n detail.omittedMissingContributorCount,\n Math.max(0, detail.missingContributorIds.length - 32),\n ),\n });\n }\n}\n\nexport class TaaUnavailableError extends Error {\n readonly code = 'taa-unavailable' as const;\n readonly expected =\n 'Standard TAA has a renderable rgba16float target and a complete resolve path';\n readonly hint =\n 'enable rgba16float rendering or select none/fxaa explicitly; do not treat TAA as no-AA';\n readonly detail: {\n readonly reason: 'capability' | 'topology' | 'history';\n readonly observed?: string;\n };\n constructor(reason: 'capability' | 'topology' | 'history', observed?: string) {\n super(`taa-unavailable: ${reason}`);\n this.name = 'TaaUnavailableError';\n this.detail = observed === undefined ? { reason } : { reason, observed };\n }\n}\n\nexport interface FrameReceiptStaleDetail {\n readonly frameId: number;\n readonly receiptGeneration: number;\n readonly currentGeneration: number;\n}\n\n/** Receipt-bound observation failed closed at a generation fence. */\nexport class FrameReceiptStaleError extends Error {\n readonly code = 'frame-receipt-stale' as const;\n readonly expected = 'the observation receipt belongs to the active device generation';\n readonly hint = 'draw a new frame and call observe with its returned FrameReceipt';\n readonly detail: FrameReceiptStaleDetail;\n\n constructor(detail: FrameReceiptStaleDetail) {\n super('frame receipt belongs to a retired device generation');\n this.name = 'FrameReceiptStaleError';\n this.detail = detail;\n }\n}\n\nexport interface RendererContractFailureDetail {\n readonly operation: 'construct' | 'attach' | 'draw' | 'observe';\n readonly cause: string;\n}\n\n/** Structured boundary failure while adapting an owner contract. */\nexport class RendererContractFailureError extends Error {\n readonly code = 'renderer-contract-failed' as const;\n readonly expected = 'renderer owner contracts remain valid at the public boundary';\n readonly hint = 'repair the owner contract and retry the operation';\n readonly detail: RendererContractFailureDetail;\n\n constructor(operation: RendererContractFailureDetail['operation'], cause: string) {\n super(`renderer ${operation} contract failed: ${cause}`);\n this.name = 'RendererContractFailureError';\n this.detail = { operation, cause };\n }\n}\n\nexport interface EnvironmentSourceConflictDetail {\n readonly owners: readonly {\n readonly kind: 'image' | 'atmosphere';\n readonly entityKey: number;\n readonly sourceKey: string;\n }[];\n}\n\nexport class EnvironmentSourceConflictError extends Error {\n readonly code = 'environment-source-conflict' as const;\n readonly expected = 'exactly one environment source owns the frame';\n readonly hint = 'remove all but one image or atmosphere environment owner';\n readonly detail: EnvironmentSourceConflictDetail;\n\n constructor(owners: readonly EnvironmentSourceConflictDetail['owners'][number][]) {\n super('environment source owners conflict');\n this.name = 'EnvironmentSourceConflictError';\n this.detail = { owners: owners.map((owner) => Object.freeze({ ...owner })) };\n }\n}\n\nexport interface FogCardinalityDetail {\n readonly count: number;\n}\n\nexport class FogCardinalityError extends Error {\n readonly code = 'fog-cardinality' as const;\n readonly expected = 'zero or one Fog owner contributes to a frame';\n readonly hint = 'remove extra Fog owners so the resource owner has at most one';\n readonly detail: FogCardinalityDetail;\n\n constructor(count: number) {\n super(`Fog owner cardinality is ${count}`);\n this.name = 'FogCardinalityError';\n this.detail = { count };\n }\n}\n\nexport interface TaaCapsInsufficientDetail {\n readonly required: readonly string[];\n readonly available: readonly string[];\n}\n\nexport class TaaCapsInsufficientError extends Error {\n readonly code = 'taa-caps-insufficient' as const;\n readonly expected = 'the backend exposes the capabilities required by TAA';\n readonly hint = 'select a backend with the required TAA capabilities or disable TAA on Camera';\n readonly detail: TaaCapsInsufficientDetail;\n\n constructor(required: readonly string[], available: readonly string[]) {\n super('TAA capabilities are insufficient');\n this.name = 'TaaCapsInsufficientError';\n this.detail = { required: [...required], available: [...available] };\n }\n}\n\nexport interface EnvironmentGenerationFailedDetail {\n readonly sourceKey: string;\n readonly stage: 'prepare' | 'build' | 'execute' | 'finish' | 'submit';\n}\n\nexport class EnvironmentGenerationFailedError extends Error {\n readonly code = 'environment-generation-failed' as const;\n readonly expected = 'the selected environment generation completes its owner stage';\n readonly hint = 'inspect the stage and sourceKey, then retry after correcting the environment';\n readonly detail: EnvironmentGenerationFailedDetail;\n\n constructor(sourceKey: string, stage: EnvironmentGenerationFailedDetail['stage']) {\n super(`environment generation failed during ${stage}`);\n this.name = 'EnvironmentGenerationFailedError';\n this.detail = { sourceKey, stage };\n }\n}\n\nexport interface AtmosphereInvalidParameterDetail {\n readonly field: string;\n readonly value: number;\n}\n\nexport interface AtmosphereParameterRange {\n readonly min: number;\n readonly max: number;\n}\n\nexport class AtmosphereInvalidParameterError extends Error {\n readonly code = 'atmosphere-invalid-parameter' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: AtmosphereInvalidParameterDetail;\n\n constructor(field: string, value: number, range: AtmosphereParameterRange) {\n super(`Atmosphere.${field} is invalid`);\n this.name = 'AtmosphereInvalidParameterError';\n this.detail = { field, value };\n const rangeText = Number.isFinite(range.max)\n ? `[${range.min}, ${range.max}]`\n : `>= ${range.min}`;\n this.expected = `Atmosphere.${field} must be finite and ${rangeText}`;\n this.hint = `set Atmosphere.${field} to a finite value ${rangeText}`;\n }\n}\n\nexport interface OwnerStageFailedDetail {\n readonly owner: 'environment' | 'temporal' | 'fog' | 'renderer';\n readonly stage: 'extract' | 'prepare' | 'record' | 'finish' | 'submit';\n}\n\nexport class OwnerStageFailedError extends Error {\n readonly code = 'owner-stage-failed' as const;\n readonly expected = 'the owner completes its current frame stage';\n readonly hint = 'inspect the owner and stage, keep the last-known-good frame, and retry';\n readonly detail: OwnerStageFailedDetail;\n\n constructor(owner: OwnerStageFailedDetail['owner'], stage: OwnerStageFailedDetail['stage']) {\n super(`${owner} owner failed during ${stage}`);\n this.name = 'OwnerStageFailedError';\n this.detail = { owner, stage };\n }\n}\n\nexport interface RendererOperationCause {\n readonly code: string;\n readonly expected: string;\n readonly hint: string;\n readonly detail?: unknown;\n}\n\nexport interface RendererOperationDetailByCode {\n readonly 'world-lease-invalid': {\n readonly operation: 'attach' | 'draw';\n readonly cause: RendererOperationCause;\n };\n readonly 'frame-input-invalid': {\n readonly operation: 'draw' | 'set-profile';\n readonly cause: RendererOperationCause;\n };\n readonly 'scene-projection-failed': {\n readonly operation: 'draw';\n readonly cause: RendererOperationCause;\n };\n readonly 'asset-binding-failed': {\n readonly operation: 'draw';\n readonly cause: RendererOperationCause;\n };\n readonly 'feature-plan-failed': {\n readonly operation: 'draw';\n readonly cause: RendererOperationCause;\n };\n readonly 'graph-build-failed': {\n readonly operation: 'draw' | 'set-profile';\n readonly cause: RendererOperationCause;\n };\n readonly 'device-operation-failed': {\n readonly operation: 'draw' | 'complete-frame' | 'renderer-event';\n readonly frameId?: number;\n readonly deviceGeneration?: number;\n readonly cause: RendererOperationCause;\n };\n readonly 'surface-unavailable': {\n readonly operation: 'release-surface' | 'restore-surface';\n readonly cause: RendererOperationCause;\n };\n readonly 'renderer-state-invalid': {\n readonly operation: 'draw' | 'set-profile' | 'recover' | 'dispose';\n readonly state: string;\n readonly cause?: RendererOperationCause;\n };\n readonly 'recovery-failed': {\n readonly operation: 'recover';\n readonly oldGeneration: number;\n readonly cause: RendererOperationCause;\n };\n readonly 'cleanup-failed': {\n readonly operation: 'dispose';\n readonly causes: readonly RendererOperationCause[];\n };\n}\n\nexport type RendererOperationErrorCode = keyof RendererOperationDetailByCode;\n\nconst RENDERER_OPERATION_ERROR_POLICY = {\n 'world-lease-invalid': {\n expected: 'every render World is represented by a live lease owned by this Renderer',\n hint: 'attach the World to this Renderer and use the returned lease',\n },\n 'frame-input-invalid': {\n expected: 'the frame input references attached leases and a valid immutable RenderProfile',\n hint: 'repair the frame input and retry draw or setProfile',\n },\n 'scene-projection-failed': {\n expected: 'the attached World projects into the renderer-owned RenderScene',\n hint: 'inspect the structured cause, repair the World publication, and retry draw',\n },\n 'asset-binding-failed': {\n expected: 'all frame assets resolve to valid renderer-owned bindings',\n hint: 'inspect the structured cause, rebuild or cold-cook the asset, and retry draw',\n },\n 'feature-plan-failed': {\n expected: 'every installed RenderFeature produces a valid declarative plan',\n hint: 'inspect the feature cause, repair its plan, and retry draw',\n },\n 'graph-build-failed': {\n expected: 'the Standard graph builds from the active profile and feature plans',\n hint: 'inspect the graph cause, repair the profile or plan, and retry',\n },\n 'device-operation-failed': {\n expected: 'the active device generation completes the renderer-owned operation',\n hint: 'inspect renderer state and the structured cause, then retry or recover',\n },\n 'surface-unavailable': {\n expected: 'the presentation surface accepts the requested lifecycle operation',\n hint: 'inspect renderer state, then restore the surface or create a new Renderer',\n },\n 'renderer-state-invalid': {\n expected: 'the Renderer is in a state that accepts the requested operation',\n hint: 'inspect renderer state and choose retry, restoreSurface, recover, or stop',\n },\n 'recovery-failed': {\n expected: 'one recovery attempt publishes a complete replacement device generation',\n hint: 'inspect the structured cause and retry recover after the host-selected delay',\n },\n 'cleanup-failed': {\n expected: 'Renderer disposal completes every registered cleanup in reverse ownership order',\n hint: 'inspect the ordered cleanup causes; the Renderer remains disposed and must not be reused',\n },\n} as const satisfies Readonly<\n Record<RendererOperationErrorCode, { readonly expected: string; readonly hint: string }>\n>;\n\n/** Public renderer-operation failure with a code-narrowed structured detail. */\nexport class RendererOperationError<Code extends RendererOperationErrorCode> extends Error {\n readonly code: Code;\n readonly expected: string;\n readonly hint: string;\n readonly detail: RendererOperationDetailByCode[Code];\n\n constructor(code: Code, detail: RendererOperationDetailByCode[Code]) {\n const policy = RENDERER_OPERATION_ERROR_POLICY[code];\n super(`${code}: ${policy.expected}`);\n this.name = 'RendererOperationError';\n this.code = code;\n this.expected = policy.expected;\n this.hint = policy.hint;\n this.detail = detail;\n }\n}\n\nexport type RendererExpectedOperationError = {\n readonly [Code in RendererOperationErrorCode]: RendererOperationError<Code>;\n}[RendererOperationErrorCode];\n\n// -- Points/Lines admission errors -------------------------------------------\n\nexport interface PointsLinesInvalidStyleDetail {\n readonly entity: number;\n readonly component: 'Points' | 'Lines' | 'Points/Lines';\n readonly field: string;\n readonly value: number | string | undefined;\n readonly expected: string;\n}\n\nexport class PointsLinesInvalidStyleError extends Error {\n readonly code = 'points-lines-invalid-style' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: PointsLinesInvalidStyleDetail;\n\n constructor(detail: PointsLinesInvalidStyleDetail) {\n super(`invalid ${detail.component} style at ${detail.field}`);\n this.name = 'PointsLinesInvalidStyleError';\n this.expected = detail.expected;\n this.hint = `repair entity ${detail.entity} ${detail.component}.${detail.field} and retry admission`;\n this.detail = detail;\n }\n}\n\nexport interface PointsLinesTopologyMismatchDetail {\n readonly entity: number;\n readonly submesh: number;\n readonly expected: string;\n readonly actual: string;\n}\n\nexport class PointsLinesTopologyMismatchError extends Error {\n readonly code = 'points-lines-topology-mismatch' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: PointsLinesTopologyMismatchDetail;\n\n constructor(detail: PointsLinesTopologyMismatchDetail) {\n super(`Points/Lines topology mismatch at submesh ${detail.submesh}`);\n this.name = 'PointsLinesTopologyMismatchError';\n this.expected = `submesh ${detail.submesh} topology is ${detail.expected}`;\n this.hint = `rebuild entity ${detail.entity} with ${detail.expected} geometry before retrying Points/Lines admission`;\n this.detail = detail;\n }\n}\n\nexport interface PointsLinesStyleUnsupportedDetail {\n readonly lane: string;\n readonly field: string;\n readonly member: string;\n readonly supported: readonly string[];\n}\n\nexport class PointsLinesStyleUnsupportedError extends Error {\n readonly code = 'points-lines-style-unsupported' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: PointsLinesStyleUnsupportedDetail;\n\n constructor(detail: PointsLinesStyleUnsupportedDetail) {\n super(`unsupported Points/Lines ${detail.field} member ${detail.member}`);\n this.name = 'PointsLinesStyleUnsupportedError';\n this.expected = `${detail.field} is one of ${detail.supported.join(', ')}`;\n this.hint = `use a supported Points/Lines ${detail.field} member or wait for a later milestone`;\n this.detail = detail;\n }\n}\n\nexport interface PointsLinesMaterialUnsupportedDetail {\n readonly entity: number;\n readonly material: string;\n readonly pass: string;\n readonly module: string;\n readonly reason: string;\n}\n\nexport class PointsLinesMaterialUnsupportedError extends Error {\n readonly code = 'points-lines-material-unsupported' as const;\n readonly expected = 'one engine-owned unlit forward MaterialAsset pass';\n readonly hint: string;\n readonly detail: PointsLinesMaterialUnsupportedDetail;\n\n constructor(detail: PointsLinesMaterialUnsupportedDetail) {\n super(`Points/Lines material is unsupported on entity ${detail.entity}`);\n this.name = 'PointsLinesMaterialUnsupportedError';\n this.hint = `use Materials.unlit without a shadow-caster pass for entity ${detail.entity}`;\n this.detail = detail;\n }\n}\n\nexport interface PointsLinesBudgetExceededDetail {\n readonly lane: string;\n readonly requested: number;\n readonly limit: number;\n readonly unit: 'points' | 'segments' | 'vertices' | 'indices' | 'bytes' | 'draws';\n}\n\nexport class PointsLinesBudgetExceededError extends Error {\n readonly code = 'points-lines-budget-exceeded' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: PointsLinesBudgetExceededDetail;\n\n constructor(detail: PointsLinesBudgetExceededDetail) {\n super(`Points/Lines ${detail.unit} budget exceeded`);\n this.name = 'PointsLinesBudgetExceededError';\n this.expected = `${detail.unit} <= ${detail.limit}`;\n this.hint = `reduce Points/Lines ${detail.unit} or split the entity into bounded equivalent batches`;\n this.detail = detail;\n }\n}\n\nexport interface PointsLinesPrepareFailedDetail {\n readonly owner: string;\n readonly generation: number;\n readonly stage: 'prepare';\n readonly cause: string;\n readonly lastKnownGood: boolean;\n}\n\nexport class PointsLinesPrepareFailedError extends Error {\n readonly code = 'points-lines-prepare-failed' as const;\n readonly expected = 'the complete Points/Lines candidate validates before publication';\n readonly hint: string;\n readonly detail: PointsLinesPrepareFailedDetail;\n\n constructor(detail: PointsLinesPrepareFailedDetail) {\n super(`Points/Lines prepare failed at generation ${detail.generation}`);\n this.name = 'PointsLinesPrepareFailedError';\n this.hint = detail.lastKnownGood\n ? 'retain the last known good candidate, repair the producer, and retry prepare'\n : 'repair the producer and retry prepare; the failed first candidate produces zero draw';\n this.detail = detail;\n }\n}\n\n// -- RenderTarget errors ------------------------------------------------------\n\nexport interface RenderTargetDescriptorInvalidDetail {\n readonly field: string;\n readonly value: unknown;\n readonly expected: string;\n}\n\nexport class RenderTargetDescriptorInvalidError extends Error {\n readonly code = 'render-target-descriptor-invalid' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: RenderTargetDescriptorInvalidDetail;\n\n constructor(detail: RenderTargetDescriptorInvalidDetail) {\n super(`render-target-descriptor-invalid: ${detail.field} does not satisfy ${detail.expected}`);\n this.name = 'RenderTargetDescriptorInvalidError';\n this.expected = detail.expected;\n this.hint = `set RenderTargetDescriptor.${detail.field} to the expected value, then retry create or resize`;\n this.detail = detail;\n }\n}\n\nexport interface RenderTargetCapabilityMissingDetail {\n readonly operation: 'create' | 'resize' | 'source' | 'readback';\n readonly requested: string;\n readonly capability: string;\n readonly actual: string;\n}\n\nexport class RenderTargetCapabilityMissingError extends Error {\n readonly code = 'render-target-capability-missing' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: RenderTargetCapabilityMissingDetail;\n\n constructor(detail: RenderTargetCapabilityMissingDetail) {\n super(\n `render-target-capability-missing: ${detail.capability} does not admit ${detail.requested}`,\n );\n this.name = 'RenderTargetCapabilityMissingError';\n this.expected = `${detail.capability} admits ${detail.requested}`;\n this.hint = `choose an admitted target descriptor or use a backend providing ${detail.capability}`;\n this.detail = detail;\n }\n}\n\nexport type RenderTargetStateInvalidReason =\n | 'foreign-renderer'\n | 'destroyed'\n | 'uninitialized'\n | 'generation-mismatch'\n | 'readback-without-intent';\n\nexport interface RenderTargetStateInvalidDetail {\n readonly operation: 'inspect' | 'resize' | 'source' | 'readback' | 'destroy';\n readonly reason: RenderTargetStateInvalidReason;\n readonly state: 'uninitialized' | 'candidate' | 'active' | 'rebuilding' | 'destroyed';\n readonly generation: number;\n}\n\nexport class RenderTargetStateInvalidError extends Error {\n readonly code = 'render-target-state-invalid' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: RenderTargetStateInvalidDetail;\n\n constructor(detail: RenderTargetStateInvalidDetail) {\n super(`render-target-state-invalid: ${detail.operation} cannot use ${detail.reason}`);\n this.name = 'RenderTargetStateInvalidError';\n this.expected = `target state permits ${detail.operation}`;\n this.hint =\n 'use the Renderer that created the target, then initialize, recover, or stop using the destroyed token';\n this.detail = detail;\n }\n}\n\nexport interface RenderTargetOperationFailedDetail {\n readonly operation: 'create' | 'resize' | 'source' | 'readback' | 'destroy' | 'recover';\n readonly stage: 'allocation' | 'compile' | 'write' | 'submit' | 'copy' | 'retire';\n readonly generation: number;\n readonly cause: unknown;\n readonly recovery: 'retry' | 'recover' | 'retain-last-known-good';\n}\n\nexport class RenderTargetOperationFailedError extends Error {\n readonly code = 'render-target-operation-failed' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: RenderTargetOperationFailedDetail;\n\n constructor(detail: RenderTargetOperationFailedDetail) {\n super(`render-target-operation-failed: ${detail.operation} failed during ${detail.stage}`);\n this.name = 'RenderTargetOperationFailedError';\n this.expected = `${detail.operation} completes ${detail.stage}`;\n this.hint =\n 'inspect detail.cause, then retry, recover the Renderer, or retain the last-known-good generation';\n this.detail = detail;\n }\n}\n\nexport interface ReflectionProbeBudgetExceededDetail {\n readonly actual: number;\n readonly budget: number;\n}\n\nexport class ReflectionProbeBudgetExceededError extends Error {\n readonly code = 'reflection-probe-budget-exceeded' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: ReflectionProbeBudgetExceededDetail;\n\n constructor(actual: number, budget: number) {\n super(`reflection-probe-budget-exceeded: ${actual} > ${budget}`);\n this.name = 'ReflectionProbeBudgetExceededError';\n this.expected = `reflection probe work <= ${budget}`;\n this.hint = 'reduce probe updates for this frame or raise the RenderProfile probe budget';\n this.detail = { actual, budget };\n }\n}\n\nexport interface RenderIntentInvalidDetail {\n readonly component: 'CubeCamera' | 'ReflectionProbe';\n readonly field: 'updateIntent';\n readonly value: number;\n readonly allowed: readonly [0, 1, 2];\n}\n\nexport class RenderIntentInvalidError extends Error {\n readonly code = 'render-intent-invalid' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: RenderIntentInvalidDetail;\n\n constructor(component: RenderIntentInvalidDetail['component'], value: number) {\n super(`render-intent-invalid: ${component}.updateIntent is not an admitted value`);\n this.name = 'RenderIntentInvalidError';\n this.expected = `${component}.updateIntent is one of 0, 1, or 2`;\n this.hint = `set ${component}.updateIntent to 0, 1, or 2`;\n this.detail = { component, field: 'updateIntent', value, allowed: [0, 1, 2] };\n }\n}\n\nexport interface VolumeOwnerConflictDetail {\n readonly ownerCount: number;\n}\n\nexport class VolumeOwnerConflictError extends Error {\n readonly code = 'volume-owner-conflict' as const;\n readonly expected = 'exactly one global VolumetricFog owner is authored';\n readonly hint = 'remove additional VolumetricFog owners and retry extraction';\n readonly detail: VolumeOwnerConflictDetail;\n\n constructor(ownerCount: number) {\n super(`volume-owner-conflict: received ${ownerCount} owners`);\n this.name = 'VolumeOwnerConflictError';\n this.detail = { ownerCount };\n }\n}\n\nexport interface VolumeDensityShapeMismatchDetail {\n readonly guid: string;\n readonly viewDimension: string;\n}\n\nexport class VolumeDensityShapeMismatchError extends Error {\n readonly code = 'volume-density-shape-mismatch' as const;\n readonly expected = 'density is a linear 3D TextureAsset';\n readonly hint = 'bind a verified linear texture with viewDimension 3d';\n readonly detail: VolumeDensityShapeMismatchDetail;\n\n constructor(guid: string, viewDimension: string) {\n super(`volume-density-shape-mismatch: ${viewDimension} density is not 3d`);\n this.name = 'VolumeDensityShapeMismatchError';\n this.detail = { guid, viewDimension };\n }\n}\n\nexport interface VolumeInvalidBoundsDetail {\n readonly min: readonly [number, number, number];\n readonly max: readonly [number, number, number];\n}\n\nexport class VolumeInvalidBoundsError extends Error {\n readonly code = 'volume-invalid-bounds' as const;\n readonly expected = 'bounds are finite and max is greater than min on every axis';\n readonly hint = 'set finite non-degenerate volume bounds';\n readonly detail: VolumeInvalidBoundsDetail;\n\n constructor(bounds: VolumeInvalidBoundsDetail) {\n super('volume-invalid-bounds: bounds must be finite and non-degenerate');\n this.name = 'VolumeInvalidBoundsError';\n this.detail = bounds;\n }\n}\n\nexport interface VolumeInvalidParametersDetail {\n readonly field: string;\n readonly value: unknown;\n}\n\nexport class VolumeInvalidParametersError extends Error {\n readonly code = 'volume-invalid-parameters' as const;\n readonly expected = 'volume parameters remain finite and inside their closed ranges';\n readonly hint = 'repair extinction, albedo, emission, anisotropy, or maxDistance';\n readonly detail: VolumeInvalidParametersDetail;\n\n constructor(input: { readonly maxDistance?: number; readonly anisotropy?: number }) {\n const field =\n input.maxDistance !== undefined && input.maxDistance <= 0 ? 'maxDistance' : 'parameters';\n const value = field === 'maxDistance' ? input.maxDistance : input.anisotropy;\n super(`volume-invalid-parameters: ${field} is outside the authored range`);\n this.name = 'VolumeInvalidParametersError';\n this.detail = { field, value };\n }\n}\n\nexport type VolumeError =\n | VolumeOwnerConflictError\n | VolumeDensityShapeMismatchError\n | VolumeInvalidBoundsError\n | VolumeInvalidParametersError;\n\nexport interface ProjectorBindingDetail {\n readonly guid: string;\n readonly status: 'pending' | 'invalid' | 'bind-failed';\n}\n\nexport class ProjectorBindingError extends Error {\n readonly code = 'projector-binding-failed' as const;\n readonly expected = 'authored projector is accepted and bound for both surface and volume';\n readonly hint =\n 'inspect the projector Meta/Pack receipt, repair the source, and retry with the same GUID';\n readonly detail: ProjectorBindingDetail;\n\n constructor(guid: string, status: ProjectorBindingDetail['status']) {\n super(`projector binding failed for ${guid}: ${status}`);\n this.name = 'ProjectorBindingError';\n this.detail = { guid, status };\n }\n}\n\n// -- RenderErrorCode / RenderError closed unions --------------------------------\n\n/**\n * Closed union of render-cluster error codes. AI users perform exhaustive\n * `switch (err.code)` without default; TS guards completeness.\n */\nexport type RenderErrorCode = RenderError['code'];\n\n/**\n * Closed union of the render-cluster structured error classes, each carrying a\n * `RenderErrorCode` discriminant on `.code`.\n */\nexport type RenderError =\n | LifecycleConstructionError\n | RendererExpectedOperationError\n | FrameReceiptStaleError\n | RendererContractFailureError\n | ObservationUnavailableError\n | SceneDataUnavailableError\n | TaaUnavailableError\n | ShadowInvalidConfigError\n | EquirectProjectionFailedError\n | StandardLightBudgetExceededError\n | StandardClusterIndexOverflowError\n | StandardClusterTransportUnavailableError\n | StandardProfileInvalidError\n | PointShadowAtlasUninitializedError\n | PointShadowAtlasBoundsViolationError\n | VideoUploadUnsupportedError\n | VertexStorageBufferUnavailableError\n | VertexColorVariantConflictError\n | SkinPaletteOverflowError\n | SkinMaterialMismatchError\n | MaterialSkinAttrMissingError\n | TransmissionCapabilityMissingError\n | RenderFeatureRegistrationConflictError\n | RenderFeatureStageFailedError\n | RenderFeatureCapabilityMissingError\n | RenderFeaturePassOrderConflictError\n | RenderFeaturePreparationFailedError\n | RenderFeaturePreparedStateMismatchError\n | RenderFeatureDrawRecordingFailedError\n | EnvironmentSourceConflictError\n | FogCardinalityError\n | TaaCapsInsufficientError\n | EnvironmentGenerationFailedError\n | AtmosphereInvalidParameterError\n | OwnerStageFailedError\n | PointsLinesInvalidStyleError\n | PointsLinesTopologyMismatchError\n | PointsLinesStyleUnsupportedError\n | PointsLinesMaterialUnsupportedError\n | PointsLinesBudgetExceededError\n | PointsLinesPrepareFailedError\n | LightResourceUnavailableError\n | RenderTargetDescriptorInvalidError\n | RenderTargetCapabilityMissingError\n | RenderTargetStateInvalidError\n | RenderTargetOperationFailedError\n | ReflectionProbeBudgetExceededError\n | RenderIntentInvalidError\n | ProjectorBindingError\n | VolumeError;\n","/**\n * Public prepared-graphics vocabulary for producer-owned RenderFeatures.\n *\n * The five prepared kinds are declarative references only: the render owner\n * retains device, resource, graph, recording, and submission ownership.\n */\n\nimport type { TextureFormat } from '@forgeax/engine-rhi';\nimport {\n err,\n type MaterialRenderState,\n ok,\n type PrimitiveTopology,\n type Result,\n} from '@forgeax/engine-types';\nimport {\n type RenderError,\n RenderFeaturePreparationFailedError,\n type RenderFeaturePreparedStateMismatchDetail,\n RenderFeaturePreparedStateMismatchError,\n} from '../errors/render';\nimport type { SceneDataTarget } from '../temporal/scene-data';\nimport type { RenderFeatureGpuBufferRef } from './prepared-gpu-work';\nimport type { RenderFeatureTargetHandle } from './targets';\nimport type { PreparedKind } from './vocabulary';\n\n/** Closed prepared kinds: pipeline, bindings, vertex/index data, and attachment. */\nexport type { PreparedKind } from './vocabulary';\n\n/** Canonical vertex layouts owned by the prepared-graphics host. */\nexport const RENDER_FEATURE_VERTEX_LAYOUTS = Object.freeze({\n positionSizeColorInstance: 'position-size-color-instance',\n billboardMaterialInstance: 'billboard-material-instance',\n topologySegmentInstance: 'topology-segment-instance',\n meshGeometryMaterialInstance: 'mesh-geometry-material-instance',\n} as const);\n\n/**\n * Opaque render-owned state identified by its prepared kind and device generation.\n * A generation change invalidates old references after device recovery or\n * pipeline replacement; features never construct or inspect backend handles.\n * Features may pass this reference back to the render owner but do not receive a\n * device, encoder, backend handle, or submit authority.\n */\nexport interface RenderFeaturePreparedRef<Kind extends PreparedKind = PreparedKind> {\n readonly kind: Kind;\n readonly generation: number;\n}\n\n/** Declarative request for a registered graphics pipeline. */\nexport interface RenderFeaturePipelineDescriptor {\n readonly shader: string;\n readonly vertexLayout: string;\n readonly colorFormats: readonly TextureFormat[];\n readonly depthFormat?: TextureFormat;\n /** Sample count of the target this pipeline will draw into. */\n readonly sampleCount?: 1 | 4;\n /** Primitive topology consumed by the prepared draw. */\n readonly topology?: PrimitiveTopology;\n /** Index scalar format when the topology consumes an index buffer. */\n readonly indexFormat?: 'uint16' | 'uint32';\n /**\n * Declarative raster/depth/blend overrides for this pipeline. The render\n * owner maps this portable material state onto the backend pipeline; a\n * feature never receives a backend pipeline descriptor or device handle.\n */\n readonly renderState?: MaterialRenderState;\n}\n\n/** Declarative request for values bound through a prepared pipeline. */\nexport interface RenderFeatureBindingsDescriptor {\n readonly pipeline: RenderFeaturePreparedRef<'pipeline'>;\n readonly values: Readonly<Record<string, unknown>> & {\n readonly group?: number;\n readonly sceneDepth?: RenderFeatureTargetHandle;\n /** Binding slot for a view-plus-scene-depth group (0 keeps legacy behavior). */\n readonly sceneDepthBinding?: number;\n };\n}\n\n/** CPU-owned vertex data and its canonical layout identity. */\nexport type RenderFeatureVertexDataDescriptor =\n | {\n readonly layout: string;\n readonly data: ArrayBufferView | readonly number[];\n readonly buffer?: never;\n }\n | {\n readonly layout: string;\n readonly buffer: RenderFeatureGpuBufferRef;\n readonly data?: never;\n };\n\n/** CPU-owned or persistent GPU-owned index data and its scalar format. */\nexport type RenderFeatureIndexDataDescriptor =\n | {\n readonly format: 'uint16' | 'uint32';\n readonly data: Uint16Array | Uint32Array;\n readonly buffer?: never;\n }\n | {\n readonly format: 'uint16' | 'uint32';\n readonly buffer: RenderFeatureGpuBufferRef;\n readonly data?: never;\n };\n\n/**\n * Feature-facing preparation facade. Call these methods during `prepare`, then\n * pass the returned references to `addGraphicsPass` during `contribute`; the\n * render owner retains resource, graph, recording, and submission ownership.\n */\nexport interface RenderFeatureGraphicsPrepare {\n /** Prepare a registered graphics pipeline without exposing backend state. */\n preparePipeline(\n name: string,\n descriptor: RenderFeaturePipelineDescriptor,\n ): Result<RenderFeaturePreparedRef<'pipeline'>, RenderError>;\n /** Prepare bindings compatible with a prepared pipeline. */\n prepareBindings(\n name: string,\n descriptor: RenderFeatureBindingsDescriptor,\n ): Result<RenderFeaturePreparedRef<'bindings'>, RenderError>;\n /** Prepare vertex data using a canonical layout identity. */\n prepareVertexData(\n name: string,\n descriptor: RenderFeatureVertexDataDescriptor,\n ): Result<RenderFeaturePreparedRef<'vertex-data'>, RenderError>;\n /** Prepare index data for an indexed draw record. */\n prepareIndexData(\n name: string,\n descriptor: RenderFeatureIndexDataDescriptor,\n ): Result<RenderFeaturePreparedRef<'index-data'>, RenderError>;\n}\n\n/** A color target declared by a graphics pass. */\nexport interface RenderFeatureColorAttachment {\n readonly resource: string | RenderFeatureTargetHandle;\n readonly format: TextureFormat;\n readonly loadOp: 'load' | 'clear';\n readonly storeOp: 'store' | 'discard';\n}\n\n/** A depth/stencil target declared by a graphics pass. */\nexport interface RenderFeatureDepthStencilAttachment {\n readonly resource: string | RenderFeatureTargetHandle;\n readonly format: TextureFormat;\n readonly depthLoadOp: 'load' | 'clear';\n readonly depthStoreOp: 'store' | 'discard';\n}\n\n/** The attachments a graphics pass requires from the render owner. */\nexport interface RenderFeatureGraphicsPassAttachments {\n readonly colors: readonly RenderFeatureColorAttachment[];\n readonly depthStencil?: RenderFeatureDepthStencilAttachment;\n}\n\n/** One vertex slot consumed by a declarative draw record. */\nexport interface RenderFeatureVertexDataBinding {\n readonly slot: number;\n readonly resource: RenderFeaturePreparedRef<'vertex-data'>;\n}\n\n/** Non-indexed draw command. */\nexport interface RenderFeatureDrawCommand {\n readonly vertexCount: number;\n readonly instanceCount: number;\n readonly firstVertex?: number;\n readonly firstInstance?: number;\n}\n\n/** Indexed draw command. */\nexport interface RenderFeatureIndexedDrawCommand {\n readonly indexCount: number;\n readonly instanceCount: number;\n readonly firstIndex?: number;\n readonly baseVertex?: number;\n readonly firstInstance?: number;\n}\n\nexport interface RenderFeatureIndirectDrawCommand {\n readonly buffer: RenderFeatureGpuBufferRef;\n readonly offset?: number;\n}\n\n/** Index state attached to an indexed draw record. */\nexport interface RenderFeatureIndexDataBinding {\n readonly resource: RenderFeaturePreparedRef<'index-data'>;\n readonly format: 'uint16' | 'uint32';\n}\n\n/** The two supported graphics draw record shapes: vertex-only and indexed. */\nexport type RenderFeatureDrawRecord =\n | {\n readonly kind: 'draw';\n readonly pipeline: RenderFeaturePreparedRef<'pipeline'>;\n readonly bindings: readonly RenderFeaturePreparedRef<'bindings'>[];\n readonly vertexData: readonly RenderFeatureVertexDataBinding[];\n /** Explicit fullscreen contract: the vertex shader owns vertex_index. */\n readonly vertexLayout?: 'none';\n readonly indexData?: RenderFeatureIndexDataBinding;\n readonly command: RenderFeatureDrawCommand;\n }\n | {\n readonly kind: 'draw-indirect';\n readonly pipeline: RenderFeaturePreparedRef<'pipeline'>;\n readonly bindings: readonly RenderFeaturePreparedRef<'bindings'>[];\n readonly vertexData: readonly RenderFeatureVertexDataBinding[];\n readonly vertexLayout?: 'none';\n readonly indexData?: RenderFeatureIndexDataBinding;\n readonly command: RenderFeatureIndirectDrawCommand;\n }\n | {\n readonly kind: 'draw-indexed';\n readonly pipeline: RenderFeaturePreparedRef<'pipeline'>;\n readonly bindings: readonly RenderFeaturePreparedRef<'bindings'>[];\n readonly vertexData: readonly RenderFeatureVertexDataBinding[];\n readonly vertexLayout?: 'none';\n readonly indexData: RenderFeatureIndexDataBinding | undefined;\n readonly command: RenderFeatureIndexedDrawCommand;\n }\n | {\n readonly kind: 'draw-indexed-indirect';\n readonly pipeline: RenderFeaturePreparedRef<'pipeline'>;\n readonly bindings: readonly RenderFeaturePreparedRef<'bindings'>[];\n readonly vertexData: readonly RenderFeatureVertexDataBinding[];\n readonly vertexLayout?: 'none';\n readonly indexData: RenderFeatureIndexDataBinding | undefined;\n readonly command: RenderFeatureIndirectDrawCommand;\n };\n\n/**\n * Declaration submitted to the existing graph-owned contribution staging.\n * This is a graphics extension of graph-only `addPass`, not a second graph.\n */\nexport interface RenderFeatureGraphicsPassDescriptor {\n readonly attachments: RenderFeatureGraphicsPassAttachments;\n /** Targets sampled by shaders but not attached for writing in this pass. */\n readonly sampledTargets?: readonly (RenderFeatureTargetHandle | SceneDataTarget)[];\n readonly draws: readonly RenderFeatureDrawRecord[];\n}\n\n/**\n * Prepared state projected by the render owner for pure descriptor validation.\n * The generation and opaque references are host facts, not producer-owned GPU\n * state.\n */\nexport interface RenderFeaturePreparedGraphicsState {\n readonly capabilityAvailable: boolean;\n readonly generation: number;\n readonly attachments: readonly {\n readonly resource: string | RenderFeatureTargetHandle;\n readonly format: TextureFormat;\n }[];\n readonly pipeline: RenderFeaturePreparedRef | undefined;\n /** All prepared pipelines available to the current graphics pass. */\n readonly pipelines?: readonly RenderFeaturePreparedRef[];\n readonly bindings: readonly RenderFeaturePreparedRef[];\n readonly vertexData: readonly RenderFeaturePreparedRef[];\n readonly indexData: readonly RenderFeaturePreparedRef[];\n}\n\n/** Successful validation result consumed by the render host projector. */\nexport interface RenderFeatureValidatedGraphicsPass {\n readonly acceptedDrawCount: number;\n}\n\nfunction invalid(\n featureIdentity: string,\n stage: 'prepare' | 'contribute',\n): Result<never, RenderError> {\n if (stage === 'prepare') {\n return err(\n new RenderFeaturePreparationFailedError(\n featureIdentity,\n -1,\n 'validate-prepared-state',\n 'pipeline',\n 'graphics-state',\n 'prepared-state-unavailable',\n 'next-frame',\n ),\n );\n }\n const detail: RenderFeaturePreparedStateMismatchDetail = {\n featureIdentity,\n order: -1,\n stage: 'contribute',\n operation: 'validate-graphics-pass',\n resourceKind: 'pipeline',\n reason: 'missing-prepared-state',\n missingResource: 'compatible-prepared-state',\n recovery: 'next-frame',\n };\n return err(new RenderFeaturePreparedStateMismatchError(detail));\n}\n\nfunction validRef<Kind extends PreparedKind>(\n reference: RenderFeaturePreparedRef<Kind>,\n kind: Kind,\n generation: number,\n): boolean {\n return reference.kind === kind && reference.generation === generation;\n}\n\nfunction hasAttachment(\n available: RenderFeaturePreparedGraphicsState['attachments'],\n required: RenderFeatureColorAttachment | RenderFeatureDepthStencilAttachment,\n): boolean {\n const identity = (resource: string | RenderFeatureTargetHandle): string =>\n typeof resource === 'string'\n ? `local:${resource}`\n : `pipeline:${resource.kind}:${resource.format}:${resource.sampleCount}`;\n const requiredResource = identity(required.resource);\n return available.some(\n (attachment) =>\n identity(attachment.resource) === requiredResource && attachment.format === required.format,\n );\n}\n\nfunction hasPreparedRef(\n available: readonly RenderFeaturePreparedRef[],\n required: RenderFeaturePreparedRef,\n): boolean {\n return available.some((reference) => reference === required);\n}\n\nfunction hasValidVertexContract(\n draw: RenderFeatureDrawRecord,\n state: RenderFeaturePreparedGraphicsState,\n): boolean {\n if (draw.vertexLayout === 'none') {\n return draw.kind === 'draw' && draw.vertexData.length === 0;\n }\n return (\n draw.vertexData.length > 0 &&\n draw.vertexData.every(\n (binding) =>\n validRef(binding.resource, 'vertex-data', state.generation) &&\n hasPreparedRef(state.vertexData, binding.resource),\n )\n );\n}\n\nfunction hasValidBindings(\n draw: RenderFeatureDrawRecord,\n state: RenderFeaturePreparedGraphicsState,\n): boolean {\n return (\n draw.bindings.length > 0 &&\n draw.bindings.every(\n (reference) =>\n validRef(reference, 'bindings', state.generation) &&\n hasPreparedRef(state.bindings, reference),\n )\n );\n}\n\n/** Validate a graphics declaration without touching an RHI backend. */\nexport function validateRenderFeatureGraphicsPass(\n featureIdentity: string,\n descriptor: RenderFeatureGraphicsPassDescriptor,\n state: RenderFeaturePreparedGraphicsState,\n): Result<RenderFeatureValidatedGraphicsPass, RenderError> {\n if (!state.capabilityAvailable) return invalid(featureIdentity, 'prepare');\n const pipelines = state.pipelines ?? (state.pipeline === undefined ? [] : [state.pipeline]);\n const hasVertexDraw = descriptor.draws.some((draw) => draw.vertexData.length > 0);\n if (\n pipelines.length === 0 ||\n state.bindings.length === 0 ||\n (hasVertexDraw && state.vertexData.length === 0)\n ) {\n return invalid(featureIdentity, 'prepare');\n }\n if (\n pipelines.some((reference) => !validRef(reference, 'pipeline', state.generation)) ||\n state.bindings.some((reference) => !validRef(reference, 'bindings', state.generation)) ||\n state.vertexData.some((reference) => !validRef(reference, 'vertex-data', state.generation)) ||\n state.indexData.some((reference) => !validRef(reference, 'index-data', state.generation))\n ) {\n return invalid(featureIdentity, 'contribute');\n }\n if (\n descriptor.attachments.colors.some(\n (attachment) => !hasAttachment(state.attachments, attachment),\n ) ||\n (descriptor.attachments.depthStencil !== undefined &&\n !hasAttachment(state.attachments, descriptor.attachments.depthStencil))\n ) {\n return invalid(featureIdentity, 'contribute');\n }\n\n for (const draw of descriptor.draws) {\n if (\n !validRef(draw.pipeline, 'pipeline', state.generation) ||\n !hasPreparedRef(pipelines, draw.pipeline) ||\n !hasValidBindings(draw, state) ||\n !hasValidVertexContract(draw, state)\n ) {\n return invalid(featureIdentity, 'contribute');\n }\n if (\n (draw.kind === 'draw-indirect' || draw.kind === 'draw-indexed-indirect') &&\n draw.command.buffer.generation !== state.generation\n ) {\n return invalid(featureIdentity, 'contribute');\n }\n if (draw.kind === 'draw-indexed' || draw.kind === 'draw-indexed-indirect') {\n if (\n draw.indexData === undefined ||\n !validRef(draw.indexData.resource, 'index-data', state.generation) ||\n !hasPreparedRef(state.indexData, draw.indexData.resource) ||\n state.indexData.length === 0\n ) {\n return invalid(featureIdentity, 'contribute');\n }\n } else if (draw.indexData !== undefined) {\n return invalid(featureIdentity, 'contribute');\n }\n }\n return ok({ acceptedDrawCount: descriptor.draws.length });\n}\n","import type { RenderFeatureMaterialShaderBindingContract } from '@forgeax/engine-render';\nimport {\n err,\n type MaterialAsset,\n type MaterialRenderState,\n type MeshAsset,\n ok,\n type Result,\n} from '@forgeax/engine-types';\nimport type { ParticleRendererSource } from '@forgeax/engine-vfx';\n\ntype ParticleRendererKind = ParticleRendererSource['kind'];\ntype ParticleTopologyRenderer = Extract<ParticleRendererSource, { readonly capacity: number }>;\ntype ParticleTopologyKind = ParticleTopologyRenderer['kind'];\n\nexport const PARTICLE_SHADER_IDENTIFIERS = Object.freeze({\n billboard: 'forgeax::vfx-render.particles.billboard',\n mesh: 'forgeax::vfx-render.particles.mesh',\n ribbon: 'forgeax::vfx-render.particles.ribbon',\n trail: 'forgeax::vfx-render.particles.trail',\n beam: 'forgeax::vfx-render.particles.beam',\n});\n\nexport interface TopologyResourcePlan {\n readonly topology: ParticleTopologyKind;\n readonly capacity: number;\n readonly vertexBytes: number;\n readonly indexBytes: number;\n readonly indirectBytes: number;\n readonly resourceKey: string;\n readonly historyLength?: number;\n readonly stripKey?: 'alive-index';\n readonly endpointField?: 'velocity';\n}\n\nexport interface TopologyResourceError {\n readonly code: 'vfx-topology-resource-invalid';\n readonly expected: string;\n readonly hint: string;\n readonly detail: { readonly path: string };\n}\n\nexport function createTopologyResourcePlan(\n renderer: unknown,\n): Result<TopologyResourcePlan, TopologyResourceError> {\n if (renderer === null || typeof renderer !== 'object' || Array.isArray(renderer))\n return err({\n code: 'vfx-topology-resource-invalid',\n expected: 'a topology renderer object',\n hint: 'declare a ribbon, trail, or beam renderer',\n detail: { path: 'renderer' },\n });\n const value = renderer as Partial<ParticleRendererSource> & Record<string, unknown>;\n if (value.kind !== 'ribbon' && value.kind !== 'trail' && value.kind !== 'beam')\n return err({\n code: 'vfx-topology-resource-invalid',\n expected: 'ribbon, trail, or beam',\n hint: 'do not alias topology output to billboard or mesh',\n detail: { path: 'renderer.kind' },\n });\n if (\n typeof value.capacity !== 'number' ||\n !Number.isInteger(value.capacity) ||\n value.capacity <= 0 ||\n value.capacity > 65536\n )\n return err({\n code: 'vfx-topology-resource-invalid',\n expected: 'capacity in the range 1..65536',\n hint: 'bound topology resources before allocating them',\n detail: { path: 'renderer.capacity' },\n });\n const capacity = value.capacity;\n if (value.kind === 'ribbon' && value.stripKey !== 'alive-index')\n return err({\n code: 'vfx-topology-resource-invalid',\n expected: \"stripKey 'alive-index'\",\n hint: 'use the managed alive-list order until a custom WGSL topology stage owns grouping',\n detail: { path: 'renderer.stripKey' },\n });\n if (\n value.kind === 'trail' &&\n (typeof value.historyLength !== 'number' ||\n !Number.isInteger(value.historyLength) ||\n value.historyLength <= 0 ||\n value.historyLength > 256)\n )\n return err({\n code: 'vfx-topology-resource-invalid',\n expected: 'historyLength in the range 1..256',\n hint: 'bound trail history storage',\n detail: { path: 'renderer.historyLength' },\n });\n if (value.kind === 'beam' && value.endpointField !== 'velocity')\n return err({\n code: 'vfx-topology-resource-invalid',\n expected: \"endpointField 'velocity'\",\n hint: 'use the managed velocity endpoint until a custom WGSL topology stage owns endpoints',\n detail: { path: 'renderer.endpointField' },\n });\n const vertexStride = 12 * 4;\n const segments =\n value.kind === 'trail' ? capacity * Math.max(1, (value.historyLength as number) - 1) : capacity;\n return ok({\n topology: value.kind,\n capacity,\n vertexBytes: Math.max(vertexStride, segments * vertexStride),\n indexBytes: 0,\n indirectBytes: 20,\n resourceKey: `vfx-topology-${value.kind}`,\n ...(value.kind === 'ribbon' ? { stripKey: 'alive-index' as const } : {}),\n ...(value.kind === 'trail' ? { historyLength: value.historyLength as number } : {}),\n ...(value.kind === 'beam' ? { endpointField: 'velocity' as const } : {}),\n });\n}\n\nexport interface TopologyCapacityInput {\n readonly requested: number;\n readonly produced: number;\n readonly degenerate?: number;\n}\n\nexport function topologyCapacitySnapshot(plan: TopologyResourcePlan, input: TopologyCapacityInput) {\n const produced = Math.max(0, Math.min(plan.capacity, input.produced));\n const requested = Math.max(0, input.requested);\n return {\n topology: plan.topology,\n capacity: plan.capacity,\n produced,\n dropped: Math.max(0, requested - produced),\n overflow: Math.max(0, requested - plan.capacity),\n degenerate: Math.max(0, input.degenerate ?? 0),\n } as const;\n}\n\nexport interface ParticleMaterialPass {\n readonly shader: string;\n readonly renderState?: MaterialRenderState;\n}\n\ntype ParticleBlendMode = Extract<ParticleRendererSource, { readonly kind: 'billboard' }>['blend'];\n\nconst PARTICLE_PREMULTIPLIED_ALPHA_BLEND: NonNullable<MaterialRenderState['blend']> = {\n color: { srcFactor: 'one', dstFactor: 'one-minus-src-alpha', operation: 'add' },\n alpha: { srcFactor: 'one', dstFactor: 'one-minus-src-alpha', operation: 'add' },\n};\n\nconst PARTICLE_ADDITIVE_BLEND: NonNullable<MaterialRenderState['blend']> = {\n color: { srcFactor: 'one', dstFactor: 'one', operation: 'add' },\n alpha: { srcFactor: 'one', dstFactor: 'one-minus-src-alpha', operation: 'add' },\n};\n\n/**\n * Resolve the one material pass that is meaningful for a particle projection.\n * A regular Forward pass is intentionally ignored: VFX vertex layouts are a\n * different contract, so silently accepting it would compile the wrong input\n * shape and make authored particle shaders appear to work while never running.\n */\nexport function particleMaterialPass(\n kind: ParticleRendererKind,\n material: MaterialAsset | undefined,\n): ParticleMaterialPass {\n const pass = material?.passes?.find((candidate) => candidate.name === `particle-${kind}`);\n return {\n shader: pass?.program.module ?? PARTICLE_SHADER_IDENTIFIERS[kind],\n ...(pass?.renderState === undefined\n ? {}\n : { renderState: pass.renderState as MaterialRenderState }),\n };\n}\n\n/**\n * Resolve the default pipeline state for a particle renderer.\n *\n * The built-in particle shaders emit premultiplied RGB (`rgb * alpha`). The\n * renderer's explicit blend mode therefore has to become a matching fixed\n * function state; leaving the state undefined makes transparent billboard\n * corners overwrite the scene with their zero RGB (the visible black-box\n * failure). An authored particle pass remains authoritative and bypasses\n * these defaults.\n */\nexport function particleRendererRenderState(\n kind: ParticleRendererKind,\n blend: ParticleBlendMode,\n authored: MaterialRenderState | undefined,\n): MaterialRenderState | undefined {\n if (authored !== undefined) return authored;\n const isTopology = kind === 'ribbon' || kind === 'trail' || kind === 'beam';\n if (kind !== 'billboard' && !isTopology) return undefined;\n const mode = kind === 'billboard' ? (blend ?? 'alpha') : 'alpha';\n if (mode === 'opaque-cutout') {\n return {\n cullMode: 'none',\n depthCompare: 'less-equal',\n depthWriteEnabled: true,\n };\n }\n return {\n cullMode: 'none',\n depthCompare: 'less-equal',\n depthWriteEnabled: false,\n blend: mode === 'additive' ? PARTICLE_ADDITIVE_BLEND : PARTICLE_PREMULTIPLIED_ALPHA_BLEND,\n };\n}\n\n/** True when the authored particle shader consumes the standard material bind group. */\nexport function particleMaterialUsesBindings(material: MaterialAsset | undefined): boolean {\n return (material?.parameters?.length ?? 0) > 0;\n}\n\n/**\n * Return the scene-depth binding slot required by a particle material shader.\n *\n * Custom particle shaders historically bind only the sampled depth resource at\n * group(0)/binding(0), while the renderer-owned billboard shader also consumes\n * the view UBO at binding(0) and therefore uses depth at binding(1). Keep this\n * choice derived from the renderer contract instead of assuming every\n * billboard has the built-in layout.\n */\nexport function particleMaterialSceneDepthBinding(\n contract: RenderFeatureMaterialShaderBindingContract | undefined,\n): 0 | 1 | undefined {\n if (contract === 'group-0-resource') return 0;\n if (contract === 'view-and-scene-depth') return 1;\n return undefined;\n}\n\nfunction floatAttribute(value: ArrayBuffer | Float32Array | Uint16Array | undefined): Float32Array {\n if (value instanceof Float32Array) return value;\n if (value instanceof Uint16Array) return Float32Array.from(value);\n return value === undefined ? new Float32Array() : new Float32Array(value);\n}\n\nexport function canonicalMeshVertices(mesh: MeshAsset): Float32Array {\n if (mesh.vertices.length > 0 && mesh.vertices.length % 12 === 0) return mesh.vertices;\n const positions = floatAttribute(mesh.attributes.position);\n const vertexCount = Math.floor(positions.length / 3);\n const normals = floatAttribute(mesh.attributes.normal);\n const uvs = floatAttribute(mesh.attributes.uv);\n const tangents = floatAttribute(mesh.attributes.tangent);\n const result = new Float32Array(vertexCount * 12);\n for (let index = 0; index < vertexCount; index += 1) {\n const target = index * 12;\n result.set(positions.subarray(index * 3, index * 3 + 3), target);\n result.set(\n normals.length >= index * 3 + 3 ? normals.subarray(index * 3, index * 3 + 3) : [0, 0, 1],\n target + 3,\n );\n result.set(\n uvs.length >= index * 2 + 2 ? uvs.subarray(index * 2, index * 2 + 2) : [0, 0],\n target + 6,\n );\n result.set(\n tangents.length >= index * 4 + 4 ? tangents.subarray(index * 4, index * 4 + 4) : [1, 0, 0, 1],\n target + 8,\n );\n }\n return result;\n}\n","import type { VfxGpuStageReflection } from '@forgeax/engine-vfx';\nimport type {\n RenderFeatureGpuBindingsRef,\n RenderFeatureGpuDispatch,\n} from '../../../render/src/features/prepared-gpu-work.js';\n\nconst MANAGED_STAGES = new Set(['spawn', 'update', 'scan', 'compact']);\nconst RESOURCE_NAMES = new Set([\n 'particles',\n 'runtime',\n 'aliveIndices',\n 'counters',\n 'indirect',\n 'scratch',\n 'billboardInstances',\n 'channelInputs',\n 'events',\n 'eventCounters',\n]);\nconst STAGE_ID = /^[a-z][a-z0-9-]{0,31}$/;\nconst ENTRY_POINT = /^forgeax_vfx_stage_[a-z][a-z0-9-]{0,31}_main$/;\nconst MAX_ITERATIONS = 64;\n\nexport interface VfxValidatedStage {\n readonly id: string;\n readonly entry: string;\n readonly entryPoint: string;\n readonly domain: 'particle';\n readonly resources: readonly {\n readonly name: string;\n readonly access: VfxGpuStageReflection['resources'][number]['access'];\n }[];\n readonly dependsOn: readonly string[];\n readonly iterationBudget: number;\n}\n\nexport interface VfxStageReadiness {\n readonly id: string;\n readonly state: 'ready' | 'candidate-rejected' | 'stale' | 'rebuilding';\n readonly generation: number;\n readonly lastKnownGoodGeneration?: number;\n readonly retryable: boolean;\n readonly error?: string;\n}\n\nexport interface VfxStagePlanObservation {\n readonly validatedStagePlan: VfxValidatedStagePlan;\n readonly stageReadiness: readonly VfxStageReadiness[];\n readonly stageOutput: 'active' | 'last-known-good' | 'empty';\n readonly lastKnownGoodStage:\n | { readonly fingerprint: string; readonly generation: number }\n | undefined;\n}\n\nexport interface VfxValidatedStagePlan {\n readonly stages: readonly VfxValidatedStage[];\n readonly fingerprint: string;\n readonly generation: number;\n}\n\nexport interface VfxStagePlanError {\n readonly code:\n | 'stage-id-invalid'\n | 'stage-entry-point-invalid'\n | 'stage-domain-invalid'\n | 'stage-resource-invalid'\n | 'stage-dependency-invalid'\n | 'stage-cycle'\n | 'stage-budget-invalid';\n readonly stageId: string;\n readonly hint: string;\n}\n\nexport type VfxStageRecovery = 'device-loss' | 'stale';\n\nfunction failure(\n code: VfxStagePlanError['code'],\n stageId: string,\n hint: string,\n): { ok: false; error: VfxStagePlanError } {\n return { ok: false, error: { code, stageId, hint } };\n}\n\nfunction stableStage(stage: VfxGpuStageReflection): VfxValidatedStage {\n return {\n id: stage.id,\n entry: stage.entry,\n entryPoint: stage.entryPoint,\n domain: stage.domain,\n resources: Object.freeze(\n stage.resources.map((resource) => ({ name: resource.name, access: resource.access })),\n ),\n dependsOn: Object.freeze([...stage.dependsOn]),\n iterationBudget: stage.iterationBudget,\n };\n}\n\n/** Validate the compiler reflection before a RenderFeature can contribute it. */\nexport function validatedStagePlan(\n reflection: VfxGpuStageReflection[] | readonly VfxGpuStageReflection[] | undefined,\n generation: number,\n):\n | { readonly ok: true; readonly value: VfxValidatedStagePlan }\n | { readonly ok: false; readonly error: VfxStagePlanError } {\n const source = reflection ?? [];\n const ids = new Set<string>();\n const stages: VfxValidatedStage[] = [];\n for (const stage of source) {\n if (!STAGE_ID.test(stage.id) || ids.has(stage.id)) {\n return failure(\n 'stage-id-invalid',\n stage.id,\n 'recook the effect with unique bounded stage ids',\n );\n }\n ids.add(stage.id);\n if (stage.domain !== 'particle' || MANAGED_STAGES.has(stage.domain)) {\n return failure('stage-domain-invalid', stage.id, 'use the managed particle dispatch domain');\n }\n if (!ENTRY_POINT.test(stage.entryPoint)) {\n return failure(\n 'stage-entry-point-invalid',\n stage.id,\n 'use the compiler-generated stage entry point',\n );\n }\n if (\n !Number.isInteger(stage.iterationBudget) ||\n stage.iterationBudget < 1 ||\n stage.iterationBudget > MAX_ITERATIONS\n ) {\n return failure(\n 'stage-budget-invalid',\n stage.id,\n 'use an integer iteration budget from 1 through 64',\n );\n }\n const resources = new Set<string>();\n for (const resource of stage.resources) {\n if (\n !RESOURCE_NAMES.has(resource.name) ||\n !['read', 'write', 'read-write'].includes(resource.access)\n ) {\n return failure(\n 'stage-resource-invalid',\n stage.id,\n 'declare only managed VFX resources with a supported access mode',\n );\n }\n if (resources.has(resource.name)) {\n return failure(\n 'stage-resource-invalid',\n stage.id,\n 'declare each managed VFX resource once',\n );\n }\n resources.add(resource.name);\n }\n stages.push(stableStage(stage));\n }\n const byId = new Map(stages.map((stage) => [stage.id, stage]));\n const visiting = new Set<string>();\n const visited = new Set<string>();\n const ordered: VfxValidatedStage[] = [];\n const visit = (stage: VfxValidatedStage): VfxStagePlanError | undefined => {\n if (visited.has(stage.id)) return undefined;\n if (visiting.has(stage.id))\n return {\n code: 'stage-cycle',\n stageId: stage.id,\n hint: 'remove the stage dependency cycle and recook the effect',\n };\n visiting.add(stage.id);\n for (const dependency of stage.dependsOn) {\n if (MANAGED_STAGES.has(dependency)) continue;\n const dependencyStage = byId.get(dependency);\n if (dependencyStage === undefined) {\n return {\n code: 'stage-dependency-invalid',\n stageId: stage.id,\n hint: 'declare every stage dependency or use a managed stage',\n };\n }\n const error = visit(dependencyStage);\n if (error !== undefined) return error;\n }\n visiting.delete(stage.id);\n visited.add(stage.id);\n ordered.push(stage);\n return undefined;\n };\n for (const stage of stages) {\n const error = visit(stage);\n if (error !== undefined) return { ok: false, error };\n }\n const normalized = Object.freeze(ordered);\n return {\n ok: true,\n value: Object.freeze({\n stages: normalized,\n fingerprint: JSON.stringify(normalized),\n generation,\n }),\n };\n}\n\nexport function stageDispatches(\n plan: VfxValidatedStagePlan,\n workgroups: number,\n bindings: RenderFeatureGpuBindingsRef,\n): readonly RenderFeatureGpuDispatch[] {\n return plan.stages.map((stage) => ({\n entryPoint: stage.entryPoint,\n workgroups: [workgroups] as const,\n bindings,\n }));\n}\n\nexport function observeStagePlan(\n candidate: ReturnType<typeof validatedStagePlan>,\n generation: number,\n lastKnownGoodStage: VfxValidatedStagePlan | undefined,\n): VfxStagePlanObservation {\n if (candidate.ok) {\n return {\n validatedStagePlan: candidate.value,\n stageReadiness: candidate.value.stages.map((stage) => ({\n id: stage.id,\n state: 'ready' as const,\n generation,\n lastKnownGoodGeneration: generation,\n retryable: false,\n })),\n stageOutput: candidate.value.stages.length === 0 ? 'empty' : 'active',\n lastKnownGoodStage:\n candidate.value.stages.length === 0\n ? lastKnownGoodStage === undefined\n ? undefined\n : {\n fingerprint: lastKnownGoodStage.fingerprint,\n generation: lastKnownGoodStage.generation,\n }\n : { fingerprint: candidate.value.fingerprint, generation },\n };\n }\n const retained = lastKnownGoodStage ?? { stages: [], fingerprint: '', generation };\n return {\n validatedStagePlan: retained,\n stageReadiness: [\n {\n id: candidate.error.stageId,\n state: 'candidate-rejected',\n generation,\n ...(lastKnownGoodStage === undefined\n ? {}\n : { lastKnownGoodGeneration: lastKnownGoodStage.generation }),\n retryable: true,\n error: candidate.error.code,\n },\n ],\n stageOutput: lastKnownGoodStage === undefined ? 'empty' : 'last-known-good',\n lastKnownGoodStage:\n lastKnownGoodStage === undefined\n ? undefined\n : {\n fingerprint: lastKnownGoodStage.fingerprint,\n generation: lastKnownGoodStage.generation,\n },\n };\n}\n\nexport function stageRecoveryReadiness(\n plan: VfxValidatedStagePlan,\n generation: number,\n recovery: VfxStageRecovery,\n): readonly VfxStageReadiness[] {\n return plan.stages.map((stage) => ({\n id: stage.id,\n state: recovery === 'stale' ? ('stale' as const) : ('rebuilding' as const),\n generation,\n lastKnownGoodGeneration: plan.generation,\n retryable: true,\n error: recovery,\n }));\n}\n","import type { EntityHandle, World } from '@forgeax/engine-ecs';\nimport { frustum } from '@forgeax/engine-math';\nimport type { RenderFeature, RenderFeaturePlan } from '@forgeax/engine-render';\nimport { GlobalTransform } from '@forgeax/engine-scene';\nimport { err, type MaterialAsset, type MeshAsset, ok } from '@forgeax/engine-types';\nimport type { ParticleRendererSource } from '@forgeax/engine-vfx';\nimport {\n VFX_GPU_RUNTIME_RESOURCE_KEY,\n type VfxGpuRuntime,\n type VfxGpuTickIntent,\n} from '@forgeax/engine-vfx';\nimport { RenderFeatureStageFailedError } from '../../../render/src/errors/render';\nimport { RENDER_FEATURE_VERTEX_LAYOUTS } from '../../../render/src/features/prepared-graphics';\nimport type { VfxDataInterfaceRegistry } from '../host/data-interface-providers.js';\nimport type { ParticleRenderCamera } from './camera.js';\nimport {\n encodeEventInputs,\n eventCapacity,\n eventInputCapacity,\n VFX_EVENT_BYTES,\n VFX_EVENT_INPUT_BYTES,\n} from './event-resources.js';\nimport {\n canonicalMeshVertices,\n createTopologyResourcePlan,\n PARTICLE_SHADER_IDENTIFIERS,\n particleMaterialPass,\n particleMaterialSceneDepthBinding,\n particleMaterialUsesBindings,\n particleRendererRenderState,\n} from './particle-resources.js';\nimport type { VfxStagePlanObservation, VfxValidatedStagePlan } from './stage-plan.js';\nimport { validatedStagePlan } from './stage-plan.js';\n\nconst IDENTITY = 'forgeax.vfx-render.gpu-particles';\nconst WORKGROUP_SIZE = 256;\nconst PARTICLE_BYTES = 80;\nconst BILLBOARD_INSTANCE_BYTES = 31 * 4;\nconst MESH_INSTANCE_BYTES = 28 * 4;\nconst COUNTERS_BYTES = 24;\nconst RUNTIME_BYTES = 72 * 4;\nconst IDENTITY_MATRIX = new Float32Array([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]);\n\ntype ParticleRendererKind = ParticleRendererSource['kind'];\ntype ParticleTopologyRenderer = Extract<ParticleRendererSource, { readonly capacity: number }>;\ntype ParticleTopologyKind = ParticleTopologyRenderer['kind'];\ntype VfxStageOutput = VfxStagePlanObservation['stageOutput'];\n\ninterface VfxRenderStageState {\n readonly stageOutput: VfxStageOutput;\n}\n\ninterface VfxRenderInspectSnapshot extends VfxRenderStageState {\n readonly topology: ParticleRendererKind;\n readonly counters: {\n readonly capacity: number;\n readonly produced: number;\n readonly dropped: number;\n };\n readonly stageReadiness: readonly unknown[];\n readonly providerReadiness: unknown;\n readonly gpuTiming: unknown;\n}\n\nexport interface VfxRenderInspectInput {\n readonly topology: ParticleRendererKind;\n readonly capacity: number;\n readonly produced: number;\n readonly dropped: number;\n readonly stageReadiness: readonly unknown[];\n readonly stageOutput?: VfxStageOutput;\n readonly providerReadiness: unknown;\n readonly gpuTiming: unknown;\n}\n\nexport function createVfxRenderInspectSnapshot(\n input: VfxRenderInspectInput,\n): VfxRenderInspectSnapshot {\n return {\n topology: input.topology,\n counters: { capacity: input.capacity, produced: input.produced, dropped: input.dropped },\n stageReadiness: input.stageReadiness,\n stageOutput: input.stageOutput ?? 'empty',\n providerReadiness: input.providerReadiness,\n gpuTiming: input.gpuTiming,\n } as const;\n}\n\nexport interface BillboardAdvancedSample {\n readonly age: number;\n readonly lifetime: number;\n readonly particleDepth: number;\n readonly sceneDepth: number;\n readonly depthAvailable: boolean;\n}\n\nexport function resolveBillboardAdvancedState(\n renderer: Extract<ParticleRendererSource, { readonly kind: 'billboard' }>,\n sample: BillboardAdvancedSample,\n) {\n if (renderer.softParticle !== undefined && !sample.depthAvailable) {\n return err({\n code: 'vfx-renderer-depth-missing' as const,\n expected: 'a scene-depth provider for soft particles',\n hint: 'attach the scene-depth data interface or disable soft particles',\n detail: { path: 'renderer.softParticle' },\n });\n }\n const sheet = renderer.textureSheet;\n const frameCount = sheet?.frameCount ?? (sheet === undefined ? 1 : sheet.columns * sheet.rows);\n const frameIndex =\n sheet === undefined || sheet.frameRate === 0\n ? 0\n : Math.min(\n frameCount - 1,\n Math.max(0, Math.floor(Math.max(0, sample.age) * sheet.frameRate)),\n );\n const softParticleFade =\n renderer.softParticle === undefined\n ? 1\n : Math.max(\n 0,\n Math.min(\n 1,\n (sample.sceneDepth - sample.particleDepth) / renderer.softParticle.fadeDistance,\n ),\n );\n return ok({\n frameIndex,\n pivot: renderer.pivot ?? ([0, 0] as const),\n softParticleFade,\n sortingKey: renderer.sorting === 'back-to-front' ? sample.particleDepth : 0,\n });\n}\n\nexport function topologyRecoveryHint(\n topology: ParticleTopologyKind,\n reason: 'capacity' | 'broken' | 'degenerate' | 'device',\n): string {\n if (reason === 'capacity')\n return `${topology} capacity overflow was bounded; increase its explicit capacity`;\n if (reason === 'broken')\n return `${topology} continuity broke; inspect its explicit source key and keep the last valid segment`;\n if (reason === 'degenerate')\n return `${topology} produced no drawable segment; preserve zero output and inspect source endpoints`;\n return `${topology} device resources recovered from the last known good generation`;\n}\n\ninterface GpuParticleFeatureOptions {\n readonly camera: { read(world: World): ParticleRenderCamera | undefined };\n readonly dataInterfaces?: Pick<VfxDataInterfaceRegistry, 'resolve'>;\n readonly material?: { read(world: World, guid: string): MaterialAsset | undefined };\n readonly mesh?: { read(world: World, guid: string): MeshAsset | undefined };\n readonly playerConsumption?: {\n readonly isEnabled: (world: World, player: EntityHandle) => boolean;\n };\n}\n\ninterface ExtractedWorld {\n readonly world: World;\n readonly runtime: VfxGpuRuntime;\n readonly camera: ParticleRenderCamera;\n readonly intents: readonly VfxGpuTickIntent[];\n}\n\ninterface ExtractedFrame {\n readonly worlds: readonly ExtractedWorld[];\n readonly frameNumber: number;\n}\n\nfunction finite(value: unknown, fallback: number): number {\n return typeof value === 'number' && Number.isFinite(value) ? value : fallback;\n}\n\nfunction vector(value: unknown, fallback: readonly number[], size: number): readonly number[] {\n return Array.isArray(value)\n ? Array.from({ length: size }, (_, index) => finite(value[index], fallback[index] ?? 0))\n : fallback;\n}\n\nfunction runtimeData(\n intent: VfxGpuTickIntent,\n camera: ParticleRenderCamera,\n material: MaterialAsset | undefined,\n localToWorld: Float32Array,\n renderer?: ParticleRendererSource,\n rendererIndex = 0,\n): Uint8Array {\n const storage = new ArrayBuffer(RUNTIME_BYTES);\n const floats = new Float32Array(storage);\n const words = new Uint32Array(storage);\n floats[0] = intent.fixedDelta;\n words[1] = intent.phaseTick;\n words[2] = intent.seed;\n words[3] = intent.playCycle;\n words[4] = intent.emitter.capacity;\n words[5] = intent.spawnCount;\n words[6] = intent.firstParticleId;\n words[7] = intent.emitter.renderers.length;\n floats.set(camera.viewProjection, 8);\n floats.set(camera.right, 24);\n floats.set(camera.up, 28);\n const values = material?.values ?? {};\n floats.set(vector(values.baseColor, [1, 1, 1, 1], 4), 32);\n const emissive = vector(values.emissive, [0, 0, 0], 3);\n floats.set(emissive, 36);\n floats[39] = finite(values.emissiveIntensity, 0);\n floats[40] = finite(values.metallic, 0);\n floats[41] = finite(values.roughness, 0.5);\n floats[42] = finite(values.clearcoat, 0);\n floats[43] = finite(values.clearcoatRoughness, 0.5);\n floats.set(localToWorld, 44);\n words[60] = rendererIndex;\n words[61] = renderer?.kind === 'trail' ? renderer.historyLength : 0;\n words[62] =\n renderer?.kind === 'ribbon' || renderer?.kind === 'trail' || renderer?.kind === 'beam'\n ? renderer.capacity\n : intent.emitter.capacity;\n words[63] =\n renderer?.kind === 'billboard' && renderer.sorting === 'back-to-front'\n ? 2\n : renderer?.kind === 'billboard' && renderer.sorting === 'emitter'\n ? 1\n : 0;\n floats[64] =\n renderer?.kind === 'billboard'\n ? (renderer.pivot?.[0] ?? 0)\n : renderer?.kind === 'ribbon' || renderer?.kind === 'trail' || renderer?.kind === 'beam'\n ? (renderer.width ?? 0.1)\n : 0.1;\n floats[65] = renderer?.kind === 'billboard' ? (renderer.pivot?.[1] ?? 0) : 0;\n floats[66] = renderer?.kind === 'billboard' ? (renderer.softParticle?.fadeDistance ?? 0) : 0;\n const sheet = renderer?.kind === 'billboard' ? renderer.textureSheet : undefined;\n floats[68] = sheet?.columns ?? 1;\n floats[69] = sheet?.rows ?? 1;\n floats[70] = sheet?.frameRate ?? 0;\n floats[71] = sheet?.frameCount ?? (sheet === undefined ? 1 : sheet.columns * sheet.rows);\n return new Uint8Array(storage);\n}\n\nfunction emitterTransform(world: World, intent: VfxGpuTickIntent): Float32Array {\n if (intent.emitter.space === 'world') return IDENTITY_MATRIX;\n const transform = world.get(intent.player, GlobalTransform);\n return transform.ok ? transform.value.world : IDENTITY_MATRIX;\n}\n\nfunction emitterVisible(\n intent: VfxGpuTickIntent,\n camera: ParticleRenderCamera,\n localToWorld: Float32Array,\n): boolean {\n const bounds = intent.emitter.bounds;\n const center =\n bounds.kind === 'sphere'\n ? bounds.center\n : ([\n (bounds.min[0] + bounds.max[0]) * 0.5,\n (bounds.min[1] + bounds.max[1]) * 0.5,\n (bounds.min[2] + bounds.max[2]) * 0.5,\n ] as const);\n const radius =\n bounds.kind === 'sphere'\n ? bounds.radius\n : Math.hypot(\n (bounds.max[0] - bounds.min[0]) * 0.5,\n (bounds.max[1] - bounds.min[1]) * 0.5,\n (bounds.max[2] - bounds.min[2]) * 0.5,\n );\n const matrix = (index: number): number => localToWorld[index] ?? 0;\n const worldCenter = new Float32Array([\n matrix(0) * center[0] + matrix(4) * center[1] + matrix(8) * center[2] + matrix(12),\n matrix(1) * center[0] + matrix(5) * center[1] + matrix(9) * center[2] + matrix(13),\n matrix(2) * center[0] + matrix(6) * center[1] + matrix(10) * center[2] + matrix(14),\n ]);\n const scale = Math.max(\n Math.hypot(matrix(0), matrix(1), matrix(2)),\n Math.hypot(matrix(4), matrix(5), matrix(6)),\n Math.hypot(matrix(8), matrix(9), matrix(10)),\n );\n const planes = frustum.fromViewProjection(frustum.create(), camera.viewProjection);\n return frustum.intersectsSphere(planes, worldCenter, radius * scale);\n}\n\nfunction resetData(size: number): Uint8Array {\n return new Uint8Array(size);\n}\n\nfunction requiresSceneDepth(intent: VfxGpuTickIntent): boolean {\n return (intent.emitter.reflection.dataInterfaces ?? []).some(\n (requirement) => requirement.kind === 'scene-depth',\n );\n}\n\nfunction planFailure(): RenderFeatureStageFailedError {\n return new RenderFeatureStageFailedError(IDENTITY, -1, 'plan', 'next-frame');\n}\n\ntype PlanResource = RenderFeaturePlan['resources'][number];\ntype PlanPass = RenderFeaturePlan['passes'][number];\n\nfunction planName(value: string, maxLength = 24): string {\n const normalized = value.toLowerCase().replaceAll(/[^a-z0-9.-]/g, '-');\n return (normalized.length === 0 ? 'unnamed' : normalized).slice(0, maxLength);\n}\n\nfunction computeBindingEntries(\n intent: VfxGpuTickIntent,\n resources: Readonly<Record<number, string>>,\n): readonly { readonly binding: number; readonly resource: string }[] {\n const declared = new Set(\n (intent.emitter.reflection.bindings[0]?.entries ?? [])\n .filter((entry) => entry.buffer !== undefined)\n .map((entry) => entry.binding),\n );\n return Object.entries(resources).flatMap(([binding, resource]) =>\n declared.has(Number(binding)) ? [{ binding: Number(binding), resource }] : [],\n );\n}\n\nfunction simulationDispatches(\n intent: VfxGpuTickIntent,\n stages: VfxValidatedStagePlan,\n): Extract<PlanPass, { readonly kind: 'compute' }>['dispatches'] {\n const groups = Math.max(1, Math.ceil(intent.emitter.capacity / WORKGROUP_SIZE));\n return [\n { kind: 'direct', entryPoint: 'forgeax_vfx_spawn_main', workgroups: [groups] },\n { kind: 'direct', entryPoint: 'forgeax_vfx_update_main', workgroups: [groups] },\n ...stages.stages.map((stage) => ({\n kind: 'direct' as const,\n entryPoint: stage.entryPoint,\n workgroups: [groups] as const,\n })),\n { kind: 'direct', entryPoint: 'forgeax_vfx_scan_blocks_main', workgroups: [groups] },\n { kind: 'direct', entryPoint: 'forgeax_vfx_scan_block_offsets_main', workgroups: [1] },\n { kind: 'direct', entryPoint: 'forgeax_vfx_add_offsets_main', workgroups: [groups] },\n { kind: 'direct', entryPoint: 'forgeax_vfx_compact_main', workgroups: [groups] },\n {\n kind: 'direct',\n entryPoint: 'forgeax_vfx_event_main',\n workgroups: [Math.max(1, Math.ceil(eventInputCapacity(intent.emitter) / 64))],\n },\n ];\n}\n\nexport function gpuParticleRenderFeature(\n options: GpuParticleFeatureOptions,\n): RenderFeature<ExtractedFrame> {\n return {\n identity: IDENTITY,\n requiredCapabilities: ['compute', 'indirectDrawing'],\n // Generated emitter programs are first-use assets. They must hand a\n // WebGPU module to the prepared feature pipeline without waiting for the\n // diagnostic-only getCompilationInfo() round trip; pipeline creation still\n // validates the module before the pass is submitted.\n shaderModuleMode: 'immediate',\n requiredMaterialShaders: Object.values(PARTICLE_SHADER_IDENTIFIERS),\n extract: (context) => {\n const extracted: ExtractedWorld[] = [];\n for (const world of context.worlds) {\n if (!world.hasResource(VFX_GPU_RUNTIME_RESOURCE_KEY)) continue;\n const camera = options.camera.read(world);\n if (camera === undefined) continue;\n const runtime = world.getResource<VfxGpuRuntime>(VFX_GPU_RUNTIME_RESOURCE_KEY);\n const intents = runtime.snapshot().filter((intent) => {\n if (options.playerConsumption?.isEnabled(world, intent.player) === false) return false;\n const requirements = intent.emitter.reflection.dataInterfaces ?? [];\n return (\n requirements.length === 0 ||\n options.dataInterfaces?.resolve(requirements, intent.instanceGeneration).ok === true\n );\n });\n extracted.push({ world, runtime, camera, intents });\n }\n return ok({ worlds: extracted, frameNumber: context.frameNumber });\n },\n plan: (frame, context) => {\n const resources: PlanResource[] = [];\n const passes: PlanPass[] = [];\n const dispatchedIntents = new Set<VfxGpuTickIntent>();\n const colorTarget =\n context.targets.find((candidate) => candidate.kind === 'color') ??\n context.targets.find((candidate) => candidate.kind === 'swapchain');\n const depthTarget = context.targets.find((candidate) => candidate.kind === 'depth');\n\n for (const [worldIndex, entry] of frame.worlds.entries()) {\n for (const [intentIndex, intent] of entry.intents.entries()) {\n if (!entry.runtime.isEmitterSessionEnabled(intent.player, intent.emitter.id)) continue;\n const localToWorld = emitterTransform(entry.world, intent);\n const visible = emitterVisible(intent, entry.camera, localToWorld);\n entry.runtime.setEmitterCameraVisibility(intent.player, intent.emitter.id, visible);\n if (!visible) continue;\n if (requiresSceneDepth(intent) && depthTarget === undefined) continue;\n\n const stagePlan = validatedStagePlan(\n intent.emitter.reflection.stages,\n intent.instanceGeneration,\n );\n if (!stagePlan.ok) return err(planFailure());\n\n const prefix = `vfx.w-${worldIndex}.i-${intentIndex}.${planName(intent.emitter.id)}`;\n const program = `${prefix}.compute-program`;\n const particles = `${prefix}.particles`;\n const runtime = `${prefix}.runtime`;\n const aliveIndices = `${prefix}.alive-indices`;\n const counters = `${prefix}.counters`;\n const indirect = `${prefix}.indirect`;\n const scratch = `${prefix}.scratch`;\n const sharedInstances = `${prefix}.shared-instances`;\n const eventInputs = `${prefix}.event-inputs`;\n const events = `${prefix}.events`;\n const bindings = `${prefix}.simulation-bindings`;\n const capacity = intent.emitter.capacity;\n const renderers = intent.emitter.renderers;\n const meshes = renderers.map((renderer) =>\n renderer.kind === 'mesh' ? options.mesh?.read(entry.world, renderer.mesh) : undefined,\n );\n const indirectWords = new Uint32Array(Math.max(1, renderers.length) * 5);\n\n for (const [rendererIndex, renderer] of renderers.entries()) {\n const mesh = meshes[rendererIndex];\n const submesh =\n renderer.kind === 'mesh' ? mesh?.submeshes[renderer.submesh ?? 0] : undefined;\n if (renderer.kind === 'mesh' && submesh === undefined) return err(planFailure());\n if (\n (renderer.kind === 'ribbon' ||\n renderer.kind === 'trail' ||\n renderer.kind === 'beam') &&\n !createTopologyResourcePlan(renderer).ok\n ) {\n return err(planFailure());\n }\n indirectWords[rendererIndex * 5] =\n renderer.kind === 'mesh'\n ? mesh?.indices === undefined\n ? (submesh?.vertexCount ?? 0)\n : (submesh?.indexCount ?? 0)\n : 6;\n indirectWords[rendererIndex * 5 + 2] =\n renderer.kind === 'mesh' && mesh?.indices !== undefined\n ? (submesh?.indexOffset ?? 0)\n : 0;\n }\n\n const scratchBytes = (capacity * 2 + Math.ceil(capacity / WORKGROUP_SIZE)) * 4;\n const eventInputBytes = Math.max(\n 4,\n eventInputCapacity(intent.emitter) * VFX_EVENT_INPUT_BYTES,\n );\n const eventBytes = Math.max(4, eventCapacity(intent.emitter) * VFX_EVENT_BYTES);\n resources.push(\n {\n kind: 'compute-program',\n name: program,\n program: {\n wgsl: intent.emitter.wgsl,\n entryPoints: intent.emitter.reflection.entryPoints,\n bindings: intent.emitter.reflection.bindings,\n },\n },\n {\n kind: 'buffer',\n name: particles,\n size: capacity * PARTICLE_BYTES,\n usage: ['storage'],\n ...(intent.reset ? { data: resetData(capacity * PARTICLE_BYTES) } : {}),\n },\n { kind: 'buffer', name: aliveIndices, size: capacity * 4, usage: ['storage'] },\n {\n kind: 'buffer',\n name: counters,\n size: COUNTERS_BYTES,\n usage: ['storage'],\n ...(intent.reset ? { data: resetData(COUNTERS_BYTES) } : {}),\n },\n {\n kind: 'buffer',\n name: indirect,\n size: indirectWords.byteLength,\n usage: ['storage', 'indirect'],\n data: indirectWords,\n },\n {\n kind: 'buffer',\n name: scratch,\n size: scratchBytes,\n usage: ['storage'],\n ...(intent.reset ? { data: resetData(scratchBytes) } : {}),\n },\n {\n kind: 'buffer',\n name: sharedInstances,\n size: capacity * Math.max(BILLBOARD_INSTANCE_BYTES, MESH_INSTANCE_BYTES),\n usage: ['storage', 'vertex'],\n },\n {\n kind: 'buffer',\n name: eventInputs,\n size: eventInputBytes,\n usage: ['storage'],\n data: encodeEventInputs(intent),\n },\n {\n kind: 'buffer',\n name: events,\n size: eventBytes,\n usage: ['storage'],\n ...(intent.reset ? { data: resetData(eventBytes) } : {}),\n },\n {\n kind: 'buffer',\n name: runtime,\n size: RUNTIME_BYTES,\n usage: ['uniform'],\n data: runtimeData(intent, entry.camera, undefined, localToWorld),\n },\n {\n kind: 'compute-bindings',\n name: bindings,\n program,\n entries: computeBindingEntries(intent, {\n 0: particles,\n 1: runtime,\n 2: aliveIndices,\n 3: counters,\n 4: indirect,\n 5: scratch,\n 6: sharedInstances,\n 8: eventInputs,\n 9: events,\n }),\n },\n );\n\n const entryPoints = new Set(intent.emitter.reflection.entryPoints);\n const dispatches = simulationDispatches(intent, stagePlan.value).filter((dispatch) =>\n entryPoints.has(dispatch.entryPoint),\n );\n if (dispatches.length > 0) {\n passes.push({\n kind: 'compute',\n name: `${prefix}.simulate`,\n program,\n bindings,\n dispatches,\n });\n dispatchedIntents.add(intent);\n }\n\n for (const [rendererIndex, renderer] of renderers.entries()) {\n const rendererPrefix = `${prefix}.renderer-${rendererIndex}`;\n const isBillboard = renderer.kind === 'billboard';\n const isTopology =\n renderer.kind === 'ribbon' || renderer.kind === 'trail' || renderer.kind === 'beam';\n const topologyPlan = isTopology ? createTopologyResourcePlan(renderer) : undefined;\n if (topologyPlan !== undefined && !topologyPlan.ok) return err(planFailure());\n const material = options.material?.read(entry.world, renderer.material);\n const materialPass = particleMaterialPass(renderer.kind, material);\n const mesh = meshes[rendererIndex];\n const submesh =\n renderer.kind === 'mesh' ? mesh?.submeshes[renderer.submesh ?? 0] : undefined;\n const indexFormat = mesh?.indices instanceof Uint32Array ? 'uint32' : 'uint16';\n const sceneDepthBinding = isBillboard\n ? particleMaterialSceneDepthBinding(\n context.materialShaderBindingContract?.(materialPass.shader) ??\n (materialPass.shader === PARTICLE_SHADER_IDENTIFIERS.billboard\n ? 'view-and-scene-depth'\n : undefined),\n )\n : undefined;\n const instances = `${rendererPrefix}.instances`;\n const history = `${rendererPrefix}.history`;\n const projectionRuntime = `${rendererPrefix}.runtime`;\n const projectionBindings = `${rendererPrefix}.compute-bindings`;\n const vertexLayout = isBillboard\n ? RENDER_FEATURE_VERTEX_LAYOUTS.billboardMaterialInstance\n : isTopology\n ? RENDER_FEATURE_VERTEX_LAYOUTS.topologySegmentInstance\n : RENDER_FEATURE_VERTEX_LAYOUTS.meshGeometryMaterialInstance;\n const instanceBytes = isTopology\n ? (topologyPlan?.value.vertexBytes ?? 16)\n : capacity * (isBillboard ? BILLBOARD_INSTANCE_BYTES : MESH_INSTANCE_BYTES);\n const historyBytes =\n renderer.kind === 'trail'\n ? Math.max(16, renderer.capacity * renderer.historyLength * 16)\n : 16;\n\n resources.push(\n {\n kind: 'buffer',\n name: instances,\n size: instanceBytes,\n usage: ['storage', 'vertex'],\n },\n {\n kind: 'buffer',\n name: history,\n size: historyBytes,\n usage: ['storage'],\n ...(intent.reset ? { data: resetData(historyBytes) } : {}),\n },\n {\n kind: 'buffer',\n name: projectionRuntime,\n size: RUNTIME_BYTES,\n usage: ['uniform'],\n data: runtimeData(\n { ...intent, fixedDelta: 0, spawnCount: 0 },\n entry.camera,\n material,\n localToWorld,\n renderer,\n rendererIndex,\n ),\n },\n {\n kind: 'compute-bindings',\n name: projectionBindings,\n program,\n entries: computeBindingEntries(intent, {\n 0: particles,\n 1: projectionRuntime,\n 2: aliveIndices,\n 3: counters,\n 4: indirect,\n 5: history,\n 6: instances,\n 8: eventInputs,\n 9: events,\n }),\n },\n );\n\n const projectionDispatches: Extract<\n PlanPass,\n { readonly kind: 'compute' }\n >['dispatches'][number][] = [];\n const pushProjection = (entryPoint: string, workgroups: number): void => {\n if (!entryPoints.has(entryPoint)) return;\n projectionDispatches.push({\n kind: 'direct',\n entryPoint,\n workgroups: [Math.max(1, workgroups)],\n });\n };\n if (isBillboard && renderer.sorting === 'back-to-front') {\n pushProjection('forgeax_vfx_sort_main', 1);\n }\n if (renderer.kind === 'trail') {\n pushProjection(\n 'forgeax_vfx_trail_history_main',\n Math.ceil(renderer.capacity / WORKGROUP_SIZE),\n );\n }\n const projectionCount =\n renderer.kind === 'trail'\n ? renderer.capacity * Math.max(1, renderer.historyLength - 1)\n : isTopology\n ? renderer.capacity\n : capacity;\n pushProjection(\n renderer.kind === 'billboard'\n ? 'forgeax_vfx_billboard_main'\n : renderer.kind === 'mesh'\n ? 'forgeax_vfx_mesh_main'\n : `forgeax_vfx_${renderer.kind}_main`,\n Math.ceil(projectionCount / WORKGROUP_SIZE),\n );\n if (projectionDispatches.length > 0) {\n passes.push({\n kind: 'compute',\n name: `${rendererPrefix}.project`,\n program,\n bindings: projectionBindings,\n dispatches: projectionDispatches,\n });\n }\n\n const graphicsProgram = `${rendererPrefix}.graphics-program`;\n const graphicsBindings = `${rendererPrefix}.graphics-bindings`;\n const vertexData = `${rendererPrefix}.vertex-data`;\n const defaultRenderState = particleRendererRenderState(\n renderer.kind,\n renderer.kind === 'billboard' ? renderer.blend : undefined,\n materialPass.renderState,\n );\n const renderState =\n isBillboard && depthTarget !== undefined\n ? { ...(defaultRenderState ?? {}), depthWriteEnabled: false }\n : defaultRenderState;\n resources.push(\n {\n kind: 'graphics-program',\n name: graphicsProgram,\n program: {\n shader: materialPass.shader,\n vertexLayout,\n colorFormats: [colorTarget?.format ?? 'rgba8unorm-srgb'],\n ...(depthTarget === undefined ? {} : { depthFormat: depthTarget.format }),\n sampleCount: colorTarget?.sampleCount ?? 1,\n topology: submesh?.topology ?? 'triangle-list',\n ...(mesh?.indices === undefined ? {} : { indexFormat }),\n ...(renderState === undefined ? {} : { renderState }),\n },\n },\n {\n kind: 'graphics-bindings',\n name: graphicsBindings,\n program: graphicsProgram,\n values: {\n group: 0,\n runtime: projectionRuntime,\n instances,\n ...(sceneDepthBinding === undefined ? {} : { sceneDepthBinding }),\n },\n ...(sceneDepthBinding !== undefined && depthTarget !== undefined\n ? { logicalTargets: { sceneDepth: depthTarget.name } }\n : {}),\n },\n { kind: 'vertex-data', name: vertexData, layout: vertexLayout, buffer: instances },\n );\n const drawBindings = [graphicsBindings];\n if (particleMaterialUsesBindings(material)) {\n const materialBindings = `${rendererPrefix}.material-bindings`;\n resources.push({\n kind: 'graphics-bindings',\n name: materialBindings,\n program: graphicsProgram,\n values: {\n group: 1,\n material: { world: worldIndex, guid: renderer.material },\n },\n });\n drawBindings.push(materialBindings);\n }\n\n const vertexBindings: { readonly slot: number; readonly resource: string }[] = [];\n let indexData:\n | { readonly resource: string; readonly format: 'uint16' | 'uint32' }\n | undefined;\n if (renderer.kind === 'mesh') {\n if (mesh === undefined) return err(planFailure());\n const geometryBuffer = `${rendererPrefix}.geometry-buffer`;\n const geometry = `${rendererPrefix}.geometry`;\n const geometryData = canonicalMeshVertices(mesh);\n resources.push(\n {\n kind: 'buffer',\n name: geometryBuffer,\n size: geometryData.byteLength,\n usage: ['vertex'],\n data: geometryData,\n },\n {\n kind: 'vertex-data',\n name: geometry,\n layout: vertexLayout,\n buffer: geometryBuffer,\n },\n );\n vertexBindings.push(\n { slot: 0, resource: geometry },\n { slot: 1, resource: vertexData },\n );\n if (mesh.indices !== undefined) {\n const indexBuffer = `${rendererPrefix}.index-buffer`;\n const indices = `${rendererPrefix}.indices`;\n resources.push(\n {\n kind: 'buffer',\n name: indexBuffer,\n size: mesh.indices.byteLength,\n usage: ['index'],\n data: mesh.indices,\n },\n {\n kind: 'index-data',\n name: indices,\n format: indexFormat,\n buffer: indexBuffer,\n },\n );\n indexData = { resource: indices, format: indexFormat };\n }\n } else {\n vertexBindings.push({ slot: 0, resource: vertexData });\n }\n\n passes.push({\n kind: 'raster',\n name: `${rendererPrefix}.raster`,\n colorAttachments: [\n {\n target: colorTarget?.name ?? 'swapchain',\n loadOp: 'load',\n storeOp: 'store',\n },\n ],\n ...(depthTarget === undefined\n ? {}\n : {\n depthStencilAttachment: {\n target: depthTarget.name,\n depthLoadOp: 'load',\n depthStoreOp: 'store',\n },\n }),\n ...(sceneDepthBinding !== undefined && depthTarget !== undefined\n ? { sampledTargets: [depthTarget.name] }\n : {}),\n draws: [\n {\n program: graphicsProgram,\n bindings: drawBindings,\n vertexData: vertexBindings,\n ...(indexData === undefined ? {} : { indexData }),\n draw: {\n kind: indexData === undefined ? 'draw-indirect' : 'draw-indexed-indirect',\n resource: indirect,\n offset: rendererIndex * 20,\n },\n },\n ],\n });\n }\n }\n }\n for (const entry of frame.worlds) {\n for (const intent of entry.intents) {\n if (dispatchedIntents.has(intent)) {\n entry.runtime.markEventDispatched(intent.player, intent.eventCounters);\n }\n }\n const lastIntent = entry.intents.at(-1);\n if (lastIntent !== undefined) entry.runtime.commit(lastIntent.sequence);\n }\n return ok<RenderFeaturePlan>({ resources, passes });\n },\n };\n}\n","import { err, ok, type Result } from '@forgeax/engine-types';\nimport {\n resolveVfxDataInterfaces,\n type VfxDataInterfaceError,\n type VfxDataInterfaceKind,\n type VfxDataInterfaceProvider,\n type VfxDataInterfaceRequirement,\n type VfxDataInterfaceResolution,\n type VfxDataInterfaceResource,\n type VfxDataInterfaceToken,\n} from '@forgeax/engine-vfx';\n\nexport type { VfxDataInterfaceProvider } from '@forgeax/engine-vfx';\n\nexport interface VfxDataInterfaceAvailabilitySource {\n readonly available: (generation: number) => boolean;\n}\n\nexport interface VfxDataInterfaceRegistry {\n readonly providers: readonly VfxDataInterfaceProvider[];\n readonly snapshot:\n | {\n readonly generation: number;\n readonly result: Result<VfxDataInterfaceResolution, VfxDataInterfaceError>;\n }\n | undefined;\n register(provider: VfxDataInterfaceProvider): Result<void, VfxDataInterfaceError>;\n resolve(\n requirements: readonly VfxDataInterfaceRequirement[],\n generation: number,\n ): Result<VfxDataInterfaceResolution, VfxDataInterfaceError>;\n}\n\nfunction duplicate(token: VfxDataInterfaceToken, providerId: string): VfxDataInterfaceError {\n return {\n code: 'vfx-data-interface-duplicate',\n expected: 'at most one provider for each reflected Data Interface token',\n hint: `remove provider ${providerId} or the existing provider for ${token} and retry`,\n detail: { token, providerId },\n };\n}\n\nfunction availableProvider<K extends VfxDataInterfaceKind>(\n token: VfxDataInterfaceProvider<K>['token'],\n kind: K,\n bindingType: VfxDataInterfaceProvider<K>['bindingType'],\n source: VfxDataInterfaceAvailabilitySource,\n): VfxDataInterfaceProvider<K> {\n return {\n id: `${token}-provider`,\n token,\n kind,\n bindingType,\n provide: (generation) => {\n if (!source.available(generation)) {\n return err({\n code: 'vfx-data-interface-missing',\n expected: `an available ${kind} provider for ${token}`,\n hint: `make ${token} available for generation ${generation} and retry rendering`,\n detail: { token, providerId: `${token}-provider` },\n });\n }\n const resource: VfxDataInterfaceResource = {\n token,\n kind,\n bindingType,\n generation,\n };\n return ok(resource);\n },\n };\n}\n\nexport function createCameraProvider(\n source: VfxDataInterfaceAvailabilitySource,\n): VfxDataInterfaceProvider<'camera'> {\n return availableProvider('vfx:camera', 'camera', 'uniform', source);\n}\n\nexport function createSceneDepthProvider(\n source: VfxDataInterfaceAvailabilitySource,\n): VfxDataInterfaceProvider<'scene-depth'> {\n return availableProvider('vfx:scene-depth', 'scene-depth', 'sampled-depth', source);\n}\n\nexport function createVfxDataInterfaceRegistry(\n initialProviders: readonly VfxDataInterfaceProvider[] = [],\n): VfxDataInterfaceRegistry {\n const entries = new Map<VfxDataInterfaceToken, VfxDataInterfaceProvider>();\n let registrationError: VfxDataInterfaceError | undefined;\n let lastSnapshot: VfxDataInterfaceRegistry['snapshot'];\n const registry: VfxDataInterfaceRegistry = {\n get providers() {\n return Object.freeze([...entries.values()]);\n },\n get snapshot() {\n return lastSnapshot;\n },\n register(provider) {\n if (entries.has(provider.token)) {\n const error = duplicate(provider.token, provider.id);\n registrationError ??= error;\n return err(error);\n }\n entries.set(provider.token, provider);\n return ok(undefined);\n },\n resolve(requirements, generation) {\n const result =\n registrationError === undefined\n ? resolveVfxDataInterfaces(requirements, [...entries.values()], generation)\n : err(registrationError);\n lastSnapshot = Object.freeze({ generation, result });\n return result;\n },\n };\n for (const provider of initialProviders) registry.register(provider);\n return registry;\n}\n","import type {\n AssetRegistryResolver,\n AssetRegistry as LegacyAssetRegistry,\n RuntimeAssetRegistry,\n} from '@forgeax/engine-assets-runtime';\nimport { getAssetRegistryResolver } from '@forgeax/engine-assets-runtime';\nimport { createWorldContext, type EntityHandle, type World } from '@forgeax/engine-ecs';\nimport type {\n Asset,\n AssetDecoderLease,\n MaterialAsset,\n MeshAsset,\n Result,\n} from '@forgeax/engine-types';\nimport { err, ok } from '@forgeax/engine-types';\nimport type {\n VfxDataInterfaceError,\n VfxDataInterfaceProvider,\n VfxDataInterfaceRequirement,\n VfxDataInterfaceResolution,\n VfxGpuPlayerInspectSnapshot,\n VfxGpuRuntimeDiagnostic,\n VfxReplayInput,\n VfxValueMap,\n} from '@forgeax/engine-vfx';\nimport {\n ParticleEffectPlayer,\n VFX_GPU_RUNTIME_RESOURCE_KEY,\n type VfxGpuRuntime,\n vfxGpuEffectContribution,\n vfxGpuEffectPackLoader,\n vfxGpuRuntimePlugin,\n} from '@forgeax/engine-vfx';\nimport type { ParticleRenderCameraSource } from '../feature/camera.js';\nimport { gpuParticleRenderFeature } from '../feature/gpu-particle-feature.js';\nimport {\n createVfxDataInterfaceRegistry,\n type VfxDataInterfaceRegistry,\n} from './data-interface-providers.js';\n\n/**\n * Public authoring projection accepted by the VFX host. Editor owns the\n * projection, while the Engine App still owns bytes/decoders/cache. Keeping\n * this small structural seam public lets the Editor pass that projection\n * without importing the runtime registry's internal module or fabricating a\n * second registry identity.\n */\nexport interface VfxAuthoringAssetRegistry {\n readonly loaders: {\n registerPackLoader(loader: unknown): void;\n };\n lookup<T extends Asset = Asset>(guid: string): T | undefined;\n readonly load?: (guid: string, kind: string) => Promise<Result<unknown, unknown>>;\n}\n\ntype AssetRegistry = LegacyAssetRegistry | RuntimeAssetRegistry | VfxAuthoringAssetRegistry;\n\nexport interface VfxRuntimeHostOptions {\n readonly camera: ParticleRenderCameraSource;\n readonly maxQueuedTicks?: number;\n readonly providers?: readonly VfxDataInterfaceProvider[];\n}\n\nexport interface VfxRuntimeHostError {\n readonly code:\n | 'vfx-host-loader-install-failed'\n | 'vfx-host-world-attach-failed'\n | 'vfx-host-world-detach-failed';\n readonly expected: string;\n readonly hint: string;\n readonly detail: { readonly cause: unknown };\n}\n\nexport interface VfxRuntimeHostControlError {\n readonly code:\n | 'vfx-host-control-world-detached'\n | 'vfx-host-control-stale-generation'\n | 'vfx-host-control-runtime-unavailable'\n | 'vfx-host-control-player-unavailable';\n readonly expected: string;\n readonly hint: string;\n readonly detail: {\n readonly requestedGeneration?: number;\n readonly currentGeneration?: number;\n readonly player?: EntityHandle;\n };\n}\n\nexport interface VfxRuntimeHostControl {\n readonly generation: number;\n replay(input: {\n readonly player: EntityHandle;\n readonly replayInput?: VfxReplayInput<VfxValueMap>;\n }): Result<{ readonly state: 'queued'; readonly generation: number }, VfxRuntimeHostControlError>;\n setEmitterSessionEnabled(input: {\n readonly player: EntityHandle;\n readonly emitterId: string;\n readonly enabled: boolean;\n }): Result<\n {\n readonly state: 'enabled' | 'disabled';\n readonly generation: number;\n },\n VfxRuntimeHostControlError\n >;\n setPlayerRenderConsumption(input: {\n readonly player: EntityHandle;\n readonly enabled: boolean;\n }): Result<\n {\n readonly state: 'enabled' | 'paused';\n readonly generation: number;\n },\n VfxRuntimeHostControlError\n >;\n}\n\nexport interface VfxRuntimeHost {\n readonly feature: ReturnType<typeof gpuParticleRenderFeature>;\n readonly dataInterfaces: VfxDataInterfaceRegistry;\n inspect(world: World): VfxRuntimeHostInspectSnapshot | undefined;\n acquireControl(world: World): Result<VfxRuntimeHostControl, VfxRuntimeHostControlError>;\n resolveDataInterfaces(input: {\n readonly requirements: readonly VfxDataInterfaceRequirement[];\n readonly generation: number;\n }): Result<VfxDataInterfaceResolution, VfxDataInterfaceError>;\n attachWorld(input: {\n readonly world: World;\n readonly assets: AssetRegistry;\n }): Promise<Result<{ readonly state: 'attached' | 'already-attached' }, VfxRuntimeHostError>>;\n detachWorld(input: {\n readonly world: World;\n }): Promise<Result<{ readonly state: 'detached' | 'not-attached' }, VfxRuntimeHostError>>;\n}\n\n/** Install the VFX owner decoder into the core registry. */\nexport function installVfxRuntimeDecoder(registry: RuntimeAssetRegistry): AssetDecoderLease {\n return registry.installDecoder(vfxGpuEffectContribution.kind, vfxGpuEffectContribution.decoder);\n}\n\nexport interface VfxRuntimeHostInspectSnapshot {\n readonly generation: number;\n /** VFX GPU resource generation; distinct from host attachment generation. */\n readonly renderGeneration: number;\n readonly players: readonly VfxGpuPlayerInspectSnapshot[];\n readonly diagnostics: readonly VfxGpuRuntimeDiagnostic[];\n}\n\ntype PluginContext = Awaited<ReturnType<typeof createWorldContext>>;\n\nfunction failure(\n code: VfxRuntimeHostError['code'],\n expected: string,\n hint: string,\n cause: unknown,\n): VfxRuntimeHostError {\n return { code, expected, hint, detail: { cause } };\n}\n\nfunction controlFailure(\n code: VfxRuntimeHostControlError['code'],\n expected: string,\n hint: string,\n detail: VfxRuntimeHostControlError['detail'] = {},\n): VfxRuntimeHostControlError {\n return { code, expected, hint, detail };\n}\n\nexport function createVfxRuntimeHost(options: VfxRuntimeHostOptions): VfxRuntimeHost {\n const registries = new WeakSet<AssetRegistry>();\n const worlds = new WeakMap<\n World,\n {\n readonly assets: AssetRegistry;\n readonly resolver: AssetRegistryResolver | undefined;\n readonly generation: number;\n readonly pluginContext: PluginContext;\n readonly renderAssets: Map<string, MaterialAsset | MeshAsset>;\n readonly pendingRenderAssets: Map<string, Promise<void>>;\n readonly unsubscribeAssets: () => void;\n catalogEpoch: number;\n }\n >();\n const pausedPlayers = new WeakMap<World, Set<EntityHandle>>();\n let nextGeneration = 1;\n const dataInterfaces = createVfxDataInterfaceRegistry(options.providers);\n const readRenderAsset = <Kind extends 'material' | 'mesh'>(\n world: World,\n guid: string,\n kind: Kind,\n ): (Kind extends 'material' ? MaterialAsset : MeshAsset) | undefined => {\n const attached = worlds.get(world);\n if (attached === undefined) return undefined;\n const key = `${kind}:${guid.toLowerCase()}`;\n const cached = attached.renderAssets.get(key);\n if (cached?.kind === kind) return cached as Kind extends 'material' ? MaterialAsset : MeshAsset;\n if ('lookup' in attached.assets) {\n const lookup = attached.assets.lookup as (guid: string) => Asset | undefined;\n // Preserve the registry receiver: the Engine-owned legacy class uses\n // `this` to read its load-state/catalogue maps. The Editor facade may\n // expose an arrow function, but calling through the owner is safe for\n // both shapes and avoids turning a lookup into a swallowed plan error.\n const legacy = lookup.call(attached.assets, guid);\n if (legacy?.kind === kind) {\n attached.renderAssets.set(key, legacy);\n return legacy as Kind extends 'material' ? MaterialAsset : MeshAsset;\n }\n }\n const resolved = attached.resolver?.lookup<MaterialAsset | MeshAsset>(guid);\n if (resolved?.kind === kind) {\n attached.renderAssets.set(key, resolved);\n return resolved as Kind extends 'material' ? MaterialAsset : MeshAsset;\n }\n if (\n 'load' in attached.assets &&\n typeof attached.assets.load === 'function' &&\n !attached.pendingRenderAssets.has(key)\n ) {\n const epoch = attached.catalogEpoch;\n const load = attached.assets.load as (\n guid: string,\n kind: string,\n ) => Promise<Result<MaterialAsset | MeshAsset, unknown>>;\n const request = load(guid, kind)\n .then((result) => {\n if (!result.ok || worlds.get(world) !== attached || attached.catalogEpoch !== epoch)\n return;\n attached.renderAssets.set(key, result.value);\n })\n .catch(() => undefined);\n attached.pendingRenderAssets.set(key, request);\n void request.finally(() => {\n if (attached.pendingRenderAssets.get(key) === request) {\n attached.pendingRenderAssets.delete(key);\n }\n });\n }\n return undefined;\n };\n const feature = gpuParticleRenderFeature({\n camera: options.camera,\n dataInterfaces,\n material: { read: (world, guid) => readRenderAsset(world, guid, 'material') },\n mesh: { read: (world, guid) => readRenderAsset(world, guid, 'mesh') },\n playerConsumption: {\n isEnabled: (world, player) => !pausedPlayers.get(world)?.has(player),\n },\n });\n return {\n feature,\n dataInterfaces,\n inspect: (world) => {\n const attached = worlds.get(world);\n if (attached === undefined || !world.hasResource(VFX_GPU_RUNTIME_RESOURCE_KEY))\n return undefined;\n const runtime = world.getResource<VfxGpuRuntime>(VFX_GPU_RUNTIME_RESOURCE_KEY);\n return Object.freeze({\n generation: attached.generation,\n renderGeneration: runtime.renderGeneration,\n players: runtime.inspectPlayers(),\n diagnostics: runtime.diagnostics(),\n });\n },\n acquireControl: (world) => {\n const attached = worlds.get(world);\n if (attached === undefined) {\n return err(\n controlFailure(\n 'vfx-host-control-world-detached',\n 'an attached VFX Runtime World',\n 'attach the World to this VfxRuntimeHost before acquiring controls',\n ),\n );\n }\n const requestedGeneration = attached.generation;\n const withRuntime = <T>(\n player: EntityHandle,\n action: (runtime: VfxGpuRuntime) => T,\n ): Result<T, VfxRuntimeHostControlError> => {\n const current = worlds.get(world);\n if (current === undefined) {\n return err(\n controlFailure(\n 'vfx-host-control-world-detached',\n `VFX host generation ${requestedGeneration} to remain attached`,\n 'reacquire controls after the World is attached again',\n { requestedGeneration },\n ),\n );\n }\n if (current.generation !== requestedGeneration) {\n return err(\n controlFailure(\n 'vfx-host-control-stale-generation',\n `VFX host generation ${requestedGeneration}`,\n 'discard this stale control lease and acquire one from the current host generation',\n { requestedGeneration, currentGeneration: current.generation },\n ),\n );\n }\n if (!world.hasResource(VFX_GPU_RUNTIME_RESOURCE_KEY)) {\n return err(\n controlFailure(\n 'vfx-host-control-runtime-unavailable',\n 'the attached World to own its VFX GPU runtime resource',\n 'repair the host attachment before retrying the preview command',\n { requestedGeneration, currentGeneration: current.generation },\n ),\n );\n }\n if (!world.get(player, ParticleEffectPlayer).ok) {\n return err(\n controlFailure(\n 'vfx-host-control-player-unavailable',\n 'a live entity with ParticleEffectPlayer in the attached World',\n 'discard the stale player handle or target a VFX player owned by this World',\n { requestedGeneration, currentGeneration: current.generation, player },\n ),\n );\n }\n return ok(action(world.getResource<VfxGpuRuntime>(VFX_GPU_RUNTIME_RESOURCE_KEY)));\n };\n const control: VfxRuntimeHostControl = {\n generation: requestedGeneration,\n replay: ({ player, replayInput }) =>\n withRuntime(player, (runtime) => {\n runtime.replay(player, replayInput);\n return Object.freeze({ state: 'queued' as const, generation: requestedGeneration });\n }),\n setEmitterSessionEnabled: ({ player, emitterId, enabled }) =>\n withRuntime(player, (runtime) => {\n runtime.setEmitterSessionEnabled(player, emitterId, enabled);\n return Object.freeze({\n state: enabled ? ('enabled' as const) : ('disabled' as const),\n generation: requestedGeneration,\n });\n }),\n setPlayerRenderConsumption: ({ player, enabled }) =>\n withRuntime(player, () => {\n let paused = pausedPlayers.get(world);\n if (enabled) {\n paused?.delete(player);\n if (paused !== undefined && paused.size === 0) pausedPlayers.delete(world);\n } else {\n paused ??= new Set();\n paused.add(player);\n pausedPlayers.set(world, paused);\n }\n return Object.freeze({\n state: enabled ? ('enabled' as const) : ('paused' as const),\n generation: requestedGeneration,\n });\n }),\n };\n return ok(Object.freeze(control));\n },\n resolveDataInterfaces: ({ requirements, generation }) =>\n dataInterfaces.resolve(requirements, generation),\n attachWorld: async ({ world, assets }) => {\n if (worlds.has(world)) return ok({ state: 'already-attached' });\n if (!registries.has(assets)) {\n try {\n // The Editor facade deliberately exposes the legacy LoaderRegistry\n // while projecting the Engine-owned App.assets instance. Prefer\n // that public authoring seam before looking for the five-action\n // runtime registry; otherwise a facade that happens to expose\n // `load` would be misclassified as a decoder owner.\n if ('loaders' in assets) {\n assets.loaders.registerPackLoader(vfxGpuEffectPackLoader);\n } else if ('installDecoder' in assets) {\n assets.installDecoder(vfxGpuEffectContribution.kind, vfxGpuEffectContribution.decoder);\n } else {\n throw new TypeError('VFX assets registry exposes neither loaders nor installDecoder');\n }\n registries.add(assets);\n } catch (cause) {\n return err(\n failure(\n 'vfx-host-loader-install-failed',\n 'the v2 VFX loader to be registered once',\n 'remove a conflicting particle-effect loader and retry attachWorld',\n cause,\n ),\n );\n }\n }\n let pluginContext: PluginContext;\n try {\n pluginContext = await createWorldContext(world, [\n vfxGpuRuntimePlugin(\n options.maxQueuedTicks === undefined ? {} : { maxQueuedTicks: options.maxQueuedTicks },\n ),\n ]);\n } catch (cause) {\n return err(\n failure(\n 'vfx-host-world-attach-failed',\n 'the World FixedUpdate VFX intent producer to install',\n 'repair the reported World registration conflict and retry',\n cause,\n ),\n );\n }\n let resolver: AssetRegistryResolver | undefined;\n if (!('loaders' in assets) && 'installDecoder' in assets) {\n try {\n resolver = getAssetRegistryResolver(assets);\n } catch {\n resolver = undefined;\n }\n }\n const attached = {\n assets,\n resolver,\n pluginContext,\n generation: nextGeneration++,\n renderAssets: new Map<string, MaterialAsset | MeshAsset>(),\n pendingRenderAssets: new Map<string, Promise<void>>(),\n catalogEpoch:\n 'snapshot' in assets && typeof assets.snapshot === 'function'\n ? assets.snapshot().epoch\n : 0,\n unsubscribeAssets: () => {},\n };\n if ('subscribe' in assets && typeof assets.subscribe === 'function') {\n attached.unsubscribeAssets = assets.subscribe((snapshot) => {\n if (snapshot.epoch === attached.catalogEpoch) return;\n attached.catalogEpoch = snapshot.epoch;\n attached.renderAssets.clear();\n attached.pendingRenderAssets.clear();\n });\n }\n worlds.set(world, attached);\n return ok({ state: 'attached' });\n },\n detachWorld: async ({ world }) => {\n const attached = worlds.get(world);\n if (attached === undefined) return ok({ state: 'not-attached' });\n try {\n await attached.pluginContext.fiber.dispose();\n } catch (cause) {\n return err(\n failure(\n 'vfx-host-world-detach-failed',\n 'the VFX FixedUpdate producer to detach exactly once',\n 'inspect the World schedule and retry detachWorld',\n cause,\n ),\n );\n }\n pausedPlayers.delete(world);\n attached.unsubscribeAssets();\n attached.renderAssets.clear();\n attached.pendingRenderAssets.clear();\n worlds.delete(world);\n return ok({ state: 'detached' });\n },\n };\n}\n"]}
1
+ {"version":3,"sources":["../src/feature/event-resources.ts","../../render/src/errors/render.ts","../../render/src/features/prepared-graphics.ts","../src/feature/particle-resources.ts","../src/feature/stage-plan.ts","../src/feature/gpu-particle-feature.ts","../src/host/data-interface-providers.ts","../src/host/vfx-runtime-host.ts"],"names":["err","ok","failure","VFX_GPU_RUNTIME_RESOURCE_KEY"],"mappings":"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","file":"index.mjs","sourcesContent":["import type { VfxGpuEmitterProgram, VfxGpuTickIntent } from '@forgeax/engine-vfx';\n\nexport const VFX_EVENT_INPUT_BYTES = 32;\nexport const VFX_EVENT_BYTES = 32;\nexport const VFX_EVENT_COUNTER_BYTES = 16;\n\nfunction channelFanOut(emitter: VfxGpuEmitterProgram, channel: string): number {\n return Math.max(\n 1,\n ...(emitter.events ?? [])\n .filter((event) => event.channel === channel)\n .map((event) => event.fanOut),\n );\n}\n\nexport function eventInputCapacity(emitter: VfxGpuEmitterProgram): number {\n return Math.max(\n 1,\n (emitter.channels ?? []).reduce((total, channel) => total + channel.capacity, 0),\n );\n}\n\nexport function eventCapacity(emitter: VfxGpuEmitterProgram): number {\n const capacity = (emitter.channels ?? []).reduce(\n (total, channel) => total + channel.capacity * channelFanOut(emitter, channel.id),\n 0,\n );\n return Math.max(1, Math.min(emitter.capacity, capacity));\n}\n\nfunction channelKey(channel: string): number {\n let hash = 2166136261;\n for (const code of channel) {\n hash ^= code.codePointAt(0) ?? 0;\n hash = Math.imul(hash, 16777619);\n }\n return hash >>> 0;\n}\n\nexport function encodeEventInputs(intent: VfxGpuTickIntent): Uint8Array {\n const capacity = eventInputCapacity(intent.emitter);\n const data = new ArrayBuffer(capacity * VFX_EVENT_INPUT_BYTES);\n const bytes = new Uint8Array(data);\n bytes.fill(0xff);\n const view = new DataView(data);\n for (const [index, input] of intent.channelInputs.entries()) {\n if (index >= capacity) break;\n const offset = index * VFX_EVENT_INPUT_BYTES;\n view.setFloat32(offset, input.payload.position[0], true);\n view.setFloat32(offset + 4, input.payload.position[1], true);\n view.setFloat32(offset + 8, input.payload.position[2], true);\n view.setFloat32(offset + 16, input.payload.strength, true);\n view.setUint32(offset + 20, input.sequence, true);\n view.setUint32(offset + 24, channelKey(input.channel), true);\n view.setUint32(offset + 28, channelFanOut(intent.emitter, input.channel), true);\n }\n return bytes;\n}\n\nexport function eventCounterData(): Uint8Array {\n return new Uint8Array(VFX_EVENT_COUNTER_BYTES);\n}\n","// @forgeax/engine-render -- render cluster error classes.\n//\n// feat-20260704-runtime-tier1-decomposition M2 / w8 (D-3): the monolithic\n// errors.ts RuntimeErrorCode / RuntimeError top-level aggregate unions are\n// decomposed into five per-cluster files (render / asset / skin / recover /\n// environment). Each cluster owns a closed *ErrorCode code union + a closed\n// *Error class union; error class names, .code literals, and .detail shapes\n// are preserved byte-for-byte (OOS-4: zero semantic change).\n//\n// The render cluster holds the shadow / HDRP cluster-forward + deferred /\n// g-buffer / point-shadow-atlas / video-upload / vertex-storage-buffer render\n// path errors. ShadowInvalidConfigError is consumed by the DirectionalLight /\n// SpotLight / PointLightShadow component validators (forward cross-directory\n// import, no cycle -- research Finding C2).\n\nimport type {\n RenderSurfaceFailureDetail,\n SurfaceFailureCode,\n SurfaceFailureKind,\n} from '@forgeax/engine-render-graph';\nimport type { DeviceResourceKind, DeviceScopeReceipt } from '../device/resource-types';\nimport type {\n PreparedKind,\n RenderFeatureCapabilityKey,\n RenderFeatureRecovery,\n RenderFeatureStage,\n} from '../features/vocabulary';\nimport type { SceneDataLane, SceneDataSchemaId } from '../temporal/scene-data';\nimport type { TransmissionCapabilityFact } from '../transmission/backdrop';\nimport type { RecoveryOutcome, RecoveryPhase } from './recover';\n\n// Public render errors keep one machine-readable order: closed `code`,\n// expected state, actionable `hint`, then typed `detail`. Consumers branch on\n// that shape and never use Error.message as a protocol.\n\nexport interface LifecycleConstructionFailureDetail {\n readonly owner: string;\n readonly generation: number;\n readonly operation: 'create' | 'dispose';\n readonly resourceKind: DeviceResourceKind;\n readonly cause: unknown;\n readonly cleanupFailures: readonly {\n readonly resourceKind: DeviceResourceKind;\n readonly cause: unknown;\n }[];\n readonly receipt: DeviceScopeReceipt;\n}\n\nexport class LifecycleConstructionError extends Error {\n readonly code = 'lifecycle-construction-failed' as const;\n readonly expected = 'all DeviceScope resources establish and terminate in order';\n readonly hint = 'inspect detail and cleanupFailures, then recover or rebuild the DeviceScope';\n readonly detail: LifecycleConstructionFailureDetail;\n\n constructor(detail: LifecycleConstructionFailureDetail) {\n super(`lifecycle-construction-failed: ${detail.resourceKind} lifecycle transaction failed`);\n this.name = 'LifecycleConstructionError';\n this.detail = detail;\n }\n}\n\nconst SURFACE_FAILURE_POLICY: Readonly<\n Record<SurfaceFailureCode, { readonly expected: string; readonly hint: string }>\n> = {\n 'surface-allocation-failed': {\n expected: 'the required surface resource can be allocated with its declared format and usage',\n hint: 'inspect the capability detail, release transient resources, and retry the candidate graph',\n },\n 'surface-attachment-failed': {\n expected: 'the float target is renderable as the declared attachment',\n hint: 'verify float color attachment support and retry without hiding the failure',\n },\n 'surface-sampled-read-failed': {\n expected: 'the float target can be sampled by the next post-processing stage',\n hint: 'verify sampled-read support for the declared format before rebuilding the graph',\n },\n 'surface-view-domain-failed': {\n expected: 'surface storage and display views preserve their declared color domains',\n hint: 'repair the explicit format/domain pair and retry the candidate graph',\n },\n 'surface-raw-endpoint-failed': {\n expected: 'the surface presentation endpoint has descriptor, acquisition, and validation proof',\n hint: 'run the concrete presentation probe; keep the last-known-good surface when proof is absent',\n },\n};\n\n/** Render-surface failure with an exhaustive code and actionable detail. */\nexport class RenderSurfaceError<\n Code extends SurfaceFailureCode = SurfaceFailureCode,\n> extends Error {\n readonly code: Code;\n readonly expected: string;\n readonly hint: string;\n readonly detail: RenderSurfaceFailureDetail;\n\n constructor(code: Code, detail: RenderSurfaceFailureDetail) {\n const policy = SURFACE_FAILURE_POLICY[code];\n if (policy === undefined) {\n throw new Error(`unknown render surface failure code: ${code}`);\n }\n super(`[RenderSurfaceError ${code}] expected: ${policy.expected}; hint: ${policy.hint}`);\n this.name = 'RenderSurfaceError';\n this.code = code;\n this.expected = policy.expected;\n this.hint = policy.hint;\n this.detail = detail;\n }\n}\n\nexport type { RenderSurfaceFailureDetail, SurfaceFailureCode, SurfaceFailureKind };\n\nexport type RenderSurfaceExpectedError = {\n readonly [Code in SurfaceFailureCode]: RenderSurfaceError<Code>;\n}[SurfaceFailureCode];\n\n/** Construct the closed surface error from its failure-stage discriminant. */\nexport function createRenderSurfaceError(\n kind: SurfaceFailureKind,\n detail: RenderSurfaceFailureDetail,\n): RenderSurfaceExpectedError {\n return new RenderSurfaceError(`surface-${kind}-failed` as SurfaceFailureCode, detail);\n}\n\nexport type LightResourceFailureReason = 'asset' | 'format' | 'capability' | 'capacity';\n\nexport interface LightResourceUnavailableDetail {\n readonly entity: number;\n readonly feature: 'ies' | 'cookie' | 'probe';\n readonly generation: number;\n readonly sourceKey: string;\n readonly reason: LightResourceFailureReason;\n}\n\nexport class LightResourceUnavailableError extends Error {\n readonly code = 'light-resource-unavailable' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: LightResourceUnavailableDetail;\n\n constructor(\n detail: LightResourceUnavailableDetail,\n expected: string,\n actual: string,\n hint: string,\n ) {\n super(`light-resource-unavailable: ${detail.feature} ${actual}`);\n this.name = 'LightResourceUnavailableError';\n this.expected = expected;\n this.hint = hint;\n this.detail = detail;\n }\n}\n\nexport function createLightResourceUnavailable(input: {\n readonly entity: number;\n readonly feature: LightResourceUnavailableDetail['feature'];\n readonly generation: number;\n readonly sourceKey: string;\n readonly reason: LightResourceFailureReason;\n readonly expected: string;\n readonly actual: string;\n readonly hint: string;\n}): LightResourceUnavailableError {\n return new LightResourceUnavailableError(\n {\n entity: input.entity,\n feature: input.feature,\n generation: input.generation,\n sourceKey: input.sourceKey,\n reason: input.reason,\n },\n input.expected,\n input.actual,\n input.hint,\n );\n}\n\nexport interface TemporalFrameSubmitDetail {\n readonly reason: 'queue-submit-failed';\n}\n\nexport class TemporalFrameSubmitError extends Error {\n readonly code = 'temporal-frame-submit-rejected' as const;\n readonly expected = 'the staged frame is accepted by queue.submit before temporal facts advance';\n readonly hint = 'inspect the queue submission and retry the frame after the device is available';\n readonly detail: TemporalFrameSubmitDetail;\n\n constructor(reason: 'queue-submit-failed') {\n super(`temporal-frame-submit-rejected: ${reason}`);\n this.name = 'TemporalFrameSubmitError';\n this.detail = { reason };\n }\n}\n// ── ShadowInvalidConfigError ──────────────────────────────────────────────\n\n/**\n * Detail for `RuntimeErrorCode 'shadow-invalid-config'`.\n *\n * The four fields are the only recovery surface: AI users read the invalid\n * field, actual value, structured bound, and reason without parsing prose.\n */\nexport type ShadowInvalidConfigBound =\n | { readonly kind: 'range'; readonly min: number; readonly max: number }\n | { readonly kind: 'lower-bound'; readonly operator: '>' | '>='; readonly value: number }\n | { readonly kind: 'allowed-values'; readonly values: readonly number[] };\n\nexport interface ShadowInvalidConfigDetail {\n readonly field: string;\n readonly actual: number;\n readonly bound: ShadowInvalidConfigBound;\n readonly reason: string;\n}\n\n/**\n * Structured error for shadow component config validation failures.\n *\n * Emitted by Directional, Point, and Spot shadow validation. All three\n * component owners share this error class so `switch (err.code)` on\n * `RuntimeErrorCode` needs one branch (charter P4 — closed-union SSOT).\n * Four-field surface:\n * - `.code = 'shadow-invalid-config'` (closed RuntimeErrorCode)\n * - `.expected` — expected-state description (programmatic predicate form)\n * - `.hint` — actionable recovery guidance (imperative; AI users paste into\n * spawn calls).\n * - `.detail = { field, actual, bound, reason }` — structured values.\n */\nexport class ShadowInvalidConfigError extends Error {\n readonly code = 'shadow-invalid-config' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: ShadowInvalidConfigDetail;\n\n constructor(\n field: string,\n actual: number,\n minOrBound: number | ShadowInvalidConfigBound,\n maxOrComparator?: number | '>' | '>=',\n reason?: string,\n ) {\n const bound: ShadowInvalidConfigBound =\n typeof minOrBound === 'number'\n ? typeof maxOrComparator === 'number'\n ? { kind: 'range', min: minOrBound, max: maxOrComparator }\n : {\n kind: 'lower-bound',\n operator: maxOrComparator === '>' ? '>' : '>=',\n value: minOrBound,\n }\n : minOrBound;\n const resolvedReason = reason ?? shadowBoundReason(bound);\n const expected = shadowBoundExpected(field, bound);\n const hint = `set ${field} to ${resolvedReason}; got ${actual}`;\n super(`shadow component .${field} is invalid: ${resolvedReason}; got ${actual}`);\n this.name = 'ShadowInvalidConfigError';\n this.hint = hint;\n this.expected = expected;\n this.detail = { field, actual, bound, reason: resolvedReason };\n }\n}\n\nfunction shadowBoundExpected(field: string, bound: ShadowInvalidConfigBound): string {\n switch (bound.kind) {\n case 'range':\n return `${field} in [${bound.min}, ${bound.max}]`;\n case 'lower-bound':\n return `${field} ${bound.operator} ${bound.value}`;\n case 'allowed-values':\n return `${field} in {${bound.values.join(', ')}}`;\n }\n}\n\nfunction shadowBoundReason(bound: ShadowInvalidConfigBound): string {\n switch (bound.kind) {\n case 'range':\n return `a value in [${bound.min}, ${bound.max}]`;\n case 'lower-bound':\n return `a value ${bound.operator} ${bound.value}`;\n case 'allowed-values':\n return `one of [${bound.values.join(', ')}]`;\n }\n}\n\n// ── EquirectProjectionFailedError ────────────────────────────────────────────\n\n/**\n * Detail for `RuntimeErrorCode 'equirect-projection-failed'`.\n *\n * Emitted when the equirect-to-cubemap IBL projection fails for the equirect\n * handle referenced by a `Skylight` / `SkyboxBackground` component. The handle\n * id is carried so AI users can trace which equirect source failed projection.\n * Degradation: the record arm records `status:'failed'`, binds the white-cube\n * fallback, fires this error ONCE, and does NOT retry the projection.\n *\n * feat-20260630 D-5: structured error with detail carrying the handle id.\n */\nexport interface EquirectProjectionFailedDetail {\n readonly handle: number;\n}\n\n/**\n * Structured error for a failed equirect-to-cubemap IBL projection.\n *\n * Emitted by the record stage when the internal cubemap projection for an\n * equirect handle returns a failure (or records `status:'failed'`). Four-field\n * surface per AGENTS.md error model:\n * - `.code = 'equirect-projection-failed'` (closed RuntimeErrorCode)\n * - `.expected` — equirect-to-cubemap projection + IBL precompute succeeds\n * - `.hint` — declare `Skylight{equirect}` with a valid HDR equirect source;\n * check `device.caps.rgba16floatRenderable`. The projection is internal —\n * there is no user upload call to retry\n * - `.detail = { handle }` — the numeric equirect handle id for diagnostics\n */\nexport class EquirectProjectionFailedError extends Error {\n readonly code = 'equirect-projection-failed' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: EquirectProjectionFailedDetail;\n\n constructor(handle: number) {\n const expected = `equirect handle ${handle} projects to a GPU cubemap + IBL precompute`;\n const hint =\n `equirect handle ${handle} referenced by Skylight/SkyboxBackground failed projection; ` +\n `declare Skylight{equirect} with a valid HDR equirect source and check device.caps.rgba16floatRenderable. ` +\n `The projection is internal (no user upload call); the record arm does not retry`;\n super(`equirect handle ${handle} cubemap projection failed`);\n this.name = 'EquirectProjectionFailedError';\n this.expected = expected;\n this.hint = hint;\n this.detail = { handle };\n }\n}\n\n// ── StandardLightBudgetExceededError ──────────────────────────────────────\n\n/** The finite local-light budget that a Standard frame agreed to admit. */\nexport interface StandardLightBudgetExceededDetail {\n readonly actual: number;\n readonly budget: number;\n}\n\n/**\n * Structured refusal for a Standard frame whose finite local-light set is\n * outside the selected profile budget. The frame is rejected as a whole; the\n * record owner must not slice the input or submit a partial membership set.\n */\nexport class StandardLightBudgetExceededError extends Error {\n readonly code = 'standard-light-budget-exceeded' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: StandardLightBudgetExceededDetail;\n\n constructor(actual: number, budget: number) {\n const expected = `light count <= ${budget}`;\n const hint =\n `${actual} finite local lights exceed Standard budget ${budget}; ` +\n 'reduce the local-light set or select a profile with a supported budget';\n super(`Standard light budget exceeded: ${actual} > ${budget}`);\n this.name = 'StandardLightBudgetExceededError';\n this.expected = expected;\n this.hint = hint;\n this.detail = { actual, budget };\n }\n}\n\n// ── StandardClusterIndexOverflowError ──────────────────────────────────────\n\n/** Cluster membership entries that could not fit the single shared index list. */\nexport interface StandardClusterIndexOverflowDetail {\n readonly actual: number;\n readonly capacity: number;\n}\n\n/**\n * Structured refusal for a membership producer that exceeded the shared\n * Cluster index-list capacity. No truncated list is uploaded and no graph is\n * submitted for the rejected frame.\n */\nexport class StandardClusterIndexOverflowError extends Error {\n readonly code = 'standard-cluster-index-overflow' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: StandardClusterIndexOverflowDetail;\n\n constructor(actual: number, capacity: number) {\n const expected = `light index list entries <= ${capacity}`;\n const hint =\n `cluster binner overflow: writeCount ${actual} exceeds capacity ${capacity}; ` +\n 'reduce finite local lights or choose a supported cluster layout';\n super(`Standard cluster index list overflow: ${actual} > ${capacity}`);\n this.name = 'StandardClusterIndexOverflowError';\n this.expected = expected;\n this.hint = hint;\n this.detail = { actual, capacity };\n }\n}\n\n// ── StandardClusterTransportUnavailableError ───────────────────────────────\n\nexport interface StandardClusterTransportUnavailableDetail {\n readonly requested: number;\n readonly admitted: 0;\n}\n\n/**\n * Structured capability refusal. Standard never turns an unproven transport\n * into a smaller direct-light lane; the caller receives the exact requested\n * local-light count and an admitted count of zero.\n */\nexport class StandardClusterTransportUnavailableError extends Error {\n readonly code = 'standard-cluster-transport-unavailable' as const;\n readonly expected = 'all requested local lights have a proven Cluster transport';\n readonly hint: string;\n readonly detail: StandardClusterTransportUnavailableDetail;\n\n constructor(\n requested: number,\n hint = 'enable a proven Cluster storage transport before drawing',\n ) {\n super(`Standard Cluster transport unavailable for ${requested} local lights`);\n this.name = 'StandardClusterTransportUnavailableError';\n this.hint = hint;\n this.detail = { requested, admitted: 0 };\n }\n}\n\n// ── StandardProfileInvalidError ───────────────────────────────────────────\n\nexport interface StandardProfileInvalidDetail {\n readonly field: string;\n readonly actual: unknown;\n}\n\n/** Structured validation failure for the single Standard profile surface. */\nexport class StandardProfileInvalidError extends Error {\n readonly code = 'standard-profile-invalid' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: StandardProfileInvalidDetail;\n\n constructor(message: string, detail?: StandardProfileInvalidDetail) {\n super(message);\n this.name = 'StandardProfileInvalidError';\n this.detail = detail ?? { field: 'profile', actual: message };\n if (this.detail.field === 'clusterGrid') {\n this.expected = 'clusterGrid.{x,y,z} each positive integer in [1, 64]';\n this.hint =\n 'set clusterGrid.x, clusterGrid.y, and clusterGrid.z to positive integers in [1, 64]';\n } else {\n this.expected = 'StandardProfile contains only supported fields and values';\n this.hint = 'repair the Standard profile fields and retry setProfile';\n }\n }\n}\n\n// ── PointShadowAtlasUninitializedError ─────────────────────────────────────\n\n/**\n * Structured error for `ShadowAtlas.faceView` called before `ensure()`\n * allocated the cube_array texture. Replaces the prior bare\n * `throw new Error()` (Round-2 F-4: P3 closed-union compliance).\n *\n * - `.code = 'point-shadow-atlas-uninitialized'`\n * - `.expected` — call `ensure()` before iterating face views\n * - `.hint` — gate `faceView` on `isAllocated()` or call `ensure()` once\n * in the per-frame extract step before recording the 6 x N caster passes\n * - `.detail = undefined` (no per-call data needed)\n */\nexport class PointShadowAtlasUninitializedError extends Error {\n readonly code = 'point-shadow-atlas-uninitialized' as const;\n readonly expected: string;\n readonly hint: string;\n\n constructor() {\n const expected = 'ShadowAtlas.ensure() invoked before faceView()';\n const hint =\n 'Gate faceView on isAllocated() or call ensure() once in the per-frame extract step before iterating face views';\n super('ShadowAtlas.faceView called before ensure(); the cube_array texture is not allocated');\n this.name = 'PointShadowAtlasUninitializedError';\n this.expected = expected;\n this.hint = hint;\n }\n}\n\n// ── PointShadowAtlasBoundsViolationError ───────────────────────────────────\n\n/**\n * Detail for `RuntimeErrorCode 'point-shadow-atlas-bounds-violation'`.\n *\n * Emitted by `ShadowAtlas.faceView` when `layer` falls outside `[0, layers)`\n * or `face` falls outside `[0, 6)`. Both axes are reported as\n * `{ axis, value, max }` so AI users discriminate without parsing the message.\n */\nexport interface PointShadowAtlasBoundsViolationDetail {\n readonly axis: 'layer' | 'face';\n readonly value: number;\n readonly max: number;\n}\n\n/**\n * Structured error for `ShadowAtlas.faceView(layer, face)` arguments outside\n * the allocated atlas range. Replaces the prior bare `throw new Error()`\n * (Round-2 F-4: P3 closed-union compliance).\n *\n * - `.code = 'point-shadow-atlas-bounds-violation'`\n * - `.expected` — `0 <= layer < layers && 0 <= face < 6`\n * - `.hint` — clamp `shadowAtlasLayer` or face index before calling\n * `faceView`; the layer cap is the renderer-owned ShadowAtlas capacity\n * - `.detail = { axis, value, max }` — discriminates layer vs face\n */\nexport class PointShadowAtlasBoundsViolationError extends Error {\n readonly code = 'point-shadow-atlas-bounds-violation' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: PointShadowAtlasBoundsViolationDetail;\n\n constructor(axis: 'layer' | 'face', value: number, max: number) {\n const expected = `0 <= ${axis} < ${max}`;\n const hint =\n axis === 'layer'\n ? `clamp PointLight.shadowAtlasLayer to [0, ${max}); the cap on layers equals PointLightShadow cardinality (4)`\n : `clamp face index to [0, ${max}); cube faces are indexed 0..5 in +X/-X/+Y/-Y/+Z/-Z order`;\n super(`ShadowAtlas.faceView ${axis} out of range: ${value} (must be in [0, ${max}))`);\n this.name = 'PointShadowAtlasBoundsViolationError';\n this.expected = expected;\n this.hint = hint;\n this.detail = { axis, value, max };\n }\n}\n\n// ── VideoUploadUnsupportedError ─────────────────────────────────────────\n\n/**\n * Structured error for `RuntimeErrorCode 'video-upload-unsupported'`\n * (feat-20260623-world-space-video-asset M3 / w11 — AC-10).\n *\n * Fired by the per-frame record stage (`videoTextureView`) when a VideoPlayer\n * entity can reach neither video upload path this frame: the general\n * `copyExternalImageToTexture` path (no host HTMLVideoElement resolved via\n * `VideoElementProvider`) AND the high-perf `GPUExternalTexture` path\n * (capability absent). The engine surfaces this explicit failure rather than\n * silently rendering a stale/garbage texture (charter P3, plan-strategy D-6).\n * - `.code = 'video-upload-unsupported'`\n * - `.expected` — at least one upload path available (host element or\n * GPUExternalTexture capability)\n * - `.hint` — actionable recovery: use a static texture or switch backend\n * - `.detail` — undefined (no narrowed detail variant)\n */\nexport class VideoUploadUnsupportedError extends Error {\n readonly code = 'video-upload-unsupported' as const;\n readonly expected: string;\n readonly hint: string;\n\n constructor() {\n const expected =\n 'at least one video upload path available: a host HTMLVideoElement (general copyExternalImageToTexture path) or GPUExternalTexture capability (high-perf path)';\n const hint =\n 'this backend exposes no usable video upload path; render a static texture instead, or switch to a WebGPU backend that supports video texture upload';\n super('video upload unsupported — no general or high-perf path available');\n this.name = 'VideoUploadUnsupportedError';\n this.expected = expected;\n this.hint = hint;\n }\n}\n\n// ── VertexStorageBufferUnavailableError ─────────────────────────────────\n\n/**\n * Structured error for missing vertex-stage storage buffer capability.\n *\n * Emitted at createRenderer time (cap-gate).\n * - `.code = 'vertex-storage-buffer-unavailable'`\n * - `.expected` — device.caps supports vertex-stage storage buffer\n * - `.hint` — switch to a WebGPU adapter with vertex storage buffer support or use uniform-buffer fallback (OOS-uniform-palette)\n * - `.detail` — undefined (no narrowed detail variant)\n */\nexport class VertexStorageBufferUnavailableError extends Error {\n readonly code = 'vertex-storage-buffer-unavailable' as const;\n readonly expected: string;\n readonly hint: string;\n\n constructor() {\n const expected =\n 'device.caps supports vertex-stage storage buffer (maxStorageBuffersPerShaderStage >= 1)';\n const hint =\n 'this device does not support vertex-stage storage buffers; skinning requires vertex-stage storage buffer access (OOS-uniform-palette fallback not implemented)';\n super('vertex-stage storage buffer unavailable — skinning cannot operate');\n this.name = 'VertexStorageBufferUnavailableError';\n this.expected = expected;\n this.hint = hint;\n }\n}\n\n// ── VertexColorVariantConflictError ───────────────────────────────────────\n\nexport interface VertexColorVariantConflictDetail {\n readonly authored: true;\n readonly authoredValue: string;\n readonly projected: boolean;\n}\n\n/** The authored color axis disagrees with the canonical geometry projection. */\nexport class VertexColorVariantConflictError extends Error {\n readonly code = 'vertex-color-variant-conflict' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: VertexColorVariantConflictDetail;\n\n constructor(authoredValue: string, projected: boolean) {\n const expected = `VERTEX_COLOR_AVAILABLE=${projected ? 'true' : 'false'}`;\n const hint =\n 'derive the shader variant from the mesh VertexLayoutProjection; COLOR_0 presence is a geometry fact';\n super(`authored vertex-color variant ${authoredValue} disagrees with projected ${expected}`);\n this.name = 'VertexColorVariantConflictError';\n this.expected = expected;\n this.hint = hint;\n this.detail = { authored: true, authoredValue, projected };\n }\n}\n\n// ── Skin palette/material validation errors ────────────────────────────────\n\n/** Detail for a palette buffer that exceeds the device storage limit. */\nexport interface SkinPaletteOverflowDetail {\n readonly requestedBytes: number;\n readonly limit: number;\n}\n\n/**\n * Structured render error for a skin palette allocation that exceeds the\n * device storage-buffer binding limit. The allocator that emits this error\n * lives in render, so the error belongs to the render union rather than the\n * renderer-independent skinning binding package.\n */\nexport class SkinPaletteOverflowError extends Error {\n readonly code = 'skin-palette-overflow' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: SkinPaletteOverflowDetail;\n\n constructor(requestedBytes: number, limit: number) {\n const expected = `skinned joint palette (${requestedBytes} B) fits within device.limits.maxStorageBufferBindingSize (${limit} B)`;\n const hint =\n 'palette buffer exceeds device maxStorageBufferBindingSize; reduce skinned entity count or split into multiple palette buffers (OOS-skin-palette-batch)';\n super(`skin palette buffer needs ${requestedBytes} B, exceeds device limit ${limit} B`);\n this.name = 'SkinPaletteOverflowError';\n this.expected = expected;\n this.hint = hint;\n this.detail = { requestedBytes, limit };\n }\n}\n\n/** Detail for a skinned entity using a non-skin material shader. */\nexport interface SkinMaterialMismatchDetail {\n readonly entity: number;\n readonly actualShader: string | undefined;\n}\n\n/** Structured render error for a Skin/non-skin-material mismatch. */\nexport class SkinMaterialMismatchError extends Error {\n readonly code = 'skin-material-mismatch' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: SkinMaterialMismatchDetail;\n\n constructor(entity: number, actualShader: string | undefined) {\n const expected = \"Skin entity's first material program module === 'forgeax::pbr-skin'\";\n const hint = `entity ${entity} has Skin but the first material program module is ${actualShader ?? '<empty>'}; load the mesh via the gltf importer (cooker auto-routes 'forgeax::pbr-skin' for skinned primitives), or remove the Skin component to render the entity unskinned with Materials.standard / Materials.unlit`;\n super(\n `Skin / material mismatch on entity ${entity}: expected forgeax::pbr-skin, got ${actualShader ?? '<empty>'}`,\n );\n this.name = 'SkinMaterialMismatchError';\n this.expected = expected;\n this.hint = hint;\n this.detail = { entity, actualShader };\n }\n}\n\n/** Detail for a pbr-skin material whose mesh lacks skin attributes. */\nexport interface MaterialSkinAttrMissingDetail {\n readonly entity: number;\n readonly missing: 'skinIndex' | 'skinWeight' | 'both';\n}\n\n/** Structured render error for a pbr-skin material/mesh attribute mismatch. */\nexport class MaterialSkinAttrMissingError extends Error {\n readonly code = 'material-skin-attr-missing' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: MaterialSkinAttrMissingDetail;\n\n constructor(entity: number, missing: 'skinIndex' | 'skinWeight' | 'both') {\n const expected = 'pbr-skin material requires mesh.attributes.skinIndex + skinWeight';\n const hint = `entity ${entity} uses forgeax::pbr-skin but its MeshAsset is missing ${missing}; switch the entity to a skinned glTF mesh authored with JOINTS_0 + WEIGHTS_0, or change the material to a non-skin shader via Materials.standard / Materials.unlit`;\n super(\n `material/skin attribute mismatch on entity ${entity}: pbr-skin material with mesh missing ${missing}`,\n );\n this.name = 'MaterialSkinAttrMissingError';\n this.expected = expected;\n this.hint = hint;\n this.detail = { entity, missing };\n }\n}\n\nexport interface TransmissionCapabilityMissingDetail {\n readonly material: string;\n readonly capability: 'transmission';\n readonly stage: 'prepare' | 'record';\n readonly lane: 'standard-forward';\n readonly format: string;\n readonly missing: readonly TransmissionCapabilityFact[];\n}\n\nexport class TransmissionCapabilityMissingError extends Error {\n readonly code = 'transmission-capability-missing' as const;\n readonly expected = 'the renderer exposes the transmission capability for this material';\n readonly hint = 'disable transmission or provide the renderer capability before drawing';\n readonly detail: TransmissionCapabilityMissingDetail;\n\n constructor(\n material: string,\n stage: 'prepare' | 'record',\n evidence: {\n readonly lane: 'standard-forward';\n readonly format: string;\n readonly missing: readonly TransmissionCapabilityFact[];\n },\n ) {\n super(`transmission capability is missing for material '${material}'`);\n this.name = 'TransmissionCapabilityMissingError';\n this.detail = { material, capability: 'transmission', stage, ...evidence };\n }\n}\n\n// -- RenderFeature errors ---------------------------------------------------\n\nexport type RenderFeatureErrorCode =\n | 'render-feature-registration-conflict'\n | 'render-feature-stage-failed'\n | 'render-feature-capability-missing'\n | 'render-feature-pass-order-conflict'\n | 'render-feature-preparation-failed'\n | 'render-feature-prepared-state-mismatch'\n | 'render-feature-draw-recording-failed';\n\nexport interface RenderFeatureRegistrationConflictDetail {\n readonly featureIdentity: string;\n readonly order: number;\n readonly conflictingOrder: number;\n}\n\nexport interface RenderFeatureCleanupFailure {\n readonly featureIdentity: string;\n readonly order: number;\n readonly code: string;\n}\n\nexport interface RenderFeatureStageFailedDetail {\n readonly featureIdentity: string;\n readonly order: number;\n readonly stage: RenderFeatureStage;\n readonly recovery: RenderFeatureRecovery;\n readonly cleanupFailures?: readonly RenderFeatureCleanupFailure[];\n}\n\nexport interface RenderFeatureCapabilityMissingDetail {\n readonly featureIdentity: string;\n readonly order: number;\n readonly capability: RenderFeatureCapabilityKey;\n}\n\nexport interface RenderFeaturePassOrderConflictDetail {\n readonly featureIdentity: string;\n readonly order: number;\n readonly passIdentity: string;\n readonly dependencyIdentity: string;\n}\n\nexport interface RenderFeaturePreparationFailedDetail {\n readonly featureIdentity: string;\n readonly order: number;\n readonly stage: 'prepare';\n readonly operation: string;\n readonly resourceKind: PreparedKind;\n readonly resourceName: string;\n readonly reason: string;\n readonly recovery: RenderFeatureRecovery;\n}\n\nexport type RenderFeaturePreparedStateMismatchDetail =\n | {\n readonly featureIdentity: string;\n readonly order: number;\n readonly stage: 'contribute';\n readonly operation: string;\n readonly resourceKind: PreparedKind;\n readonly reason: 'missing-prepared-state';\n readonly missingResource: string;\n readonly recovery: RenderFeatureRecovery;\n }\n | {\n readonly featureIdentity: string;\n readonly order: number;\n readonly stage: 'contribute';\n readonly operation: string;\n readonly resourceKind: PreparedKind;\n readonly reason: 'foreign-feature';\n readonly expectedFeatureIdentity: string;\n readonly actualFeatureIdentity: string;\n readonly recovery: RenderFeatureRecovery;\n }\n | {\n readonly featureIdentity: string;\n readonly order: number;\n readonly stage: 'contribute';\n readonly operation: string;\n readonly resourceKind: PreparedKind;\n readonly reason: 'foreign-kind';\n readonly expectedKind: PreparedKind;\n readonly actualKind: PreparedKind;\n readonly recovery: RenderFeatureRecovery;\n }\n | {\n readonly featureIdentity: string;\n readonly order: number;\n readonly stage: 'contribute';\n readonly operation: string;\n readonly resourceKind: PreparedKind;\n readonly reason: 'generation-mismatch';\n readonly expectedGeneration: number;\n readonly actualGeneration: number;\n readonly recovery: RenderFeatureRecovery;\n }\n | {\n readonly featureIdentity: string;\n readonly order: number;\n readonly stage: 'contribute';\n readonly operation: string;\n readonly resourceKind: PreparedKind;\n readonly reason: 'layout-mismatch';\n readonly expectedLayout: string;\n readonly actualLayout: string;\n readonly recovery: RenderFeatureRecovery;\n }\n | {\n readonly featureIdentity: string;\n readonly order: number;\n readonly stage: 'contribute';\n readonly operation: string;\n readonly resourceKind: PreparedKind;\n readonly reason: 'format-mismatch';\n readonly expectedFormat: string;\n readonly actualFormat: string;\n readonly recovery: RenderFeatureRecovery;\n };\n\nexport interface RenderFeatureDrawRecordingFailedDetail {\n readonly featureIdentity: string;\n readonly order: number;\n readonly stage: 'record';\n readonly operation: string;\n readonly resourceKind: PreparedKind;\n readonly reason: string;\n readonly backendReason: string;\n readonly recovery: RenderFeatureRecovery;\n}\n\nexport type RenderFeatureErrorDetailByCode = {\n 'render-feature-registration-conflict': RenderFeatureRegistrationConflictDetail;\n 'render-feature-stage-failed': RenderFeatureStageFailedDetail;\n 'render-feature-capability-missing': RenderFeatureCapabilityMissingDetail;\n 'render-feature-pass-order-conflict': RenderFeaturePassOrderConflictDetail;\n 'render-feature-preparation-failed': RenderFeaturePreparationFailedDetail;\n 'render-feature-prepared-state-mismatch': RenderFeaturePreparedStateMismatchDetail;\n 'render-feature-draw-recording-failed': RenderFeatureDrawRecordingFailedDetail;\n};\n\n/** Machine-readable four-field diagnostic exposed by every feature error. */\nexport type RenderFeatureErrorDescriptor = {\n [Code in RenderFeatureErrorCode]: {\n readonly code: Code;\n readonly expected: string;\n readonly hint: string;\n readonly detail: RenderFeatureErrorDetailByCode[Code];\n };\n}[RenderFeatureErrorCode];\n\nconst renderFeatureRecoveryHintByRecovery = {\n 'next-frame': (featureIdentity: string, stage: RenderFeatureStage) =>\n `correct '${featureIdentity}' ${stage} data and retry on the next frame`,\n 'renderer-recover': (featureIdentity: string, _stage: RenderFeatureStage) =>\n `wait for renderer recovery before retrying '${featureIdentity}'`,\n registration: (featureIdentity: string, _stage: RenderFeatureStage) =>\n `correct '${featureIdentity}' registration before retrying`,\n} satisfies Record<\n RenderFeatureRecovery,\n (featureIdentity: string, stage: RenderFeatureStage) => string\n>;\n\nexport class RenderFeatureRegistrationConflictError extends Error {\n readonly code = 'render-feature-registration-conflict' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: RenderFeatureRegistrationConflictDetail;\n\n constructor(featureIdentity: string, order: number, conflictingOrder: number) {\n const expected = `feature identity '${featureIdentity}' is unique`;\n const hint = `rename '${featureIdentity}' or remove the duplicate feature before registration`;\n super(`render feature registration conflict for '${featureIdentity}'`);\n this.name = 'RenderFeatureRegistrationConflictError';\n this.expected = expected;\n this.hint = hint;\n this.detail = { featureIdentity, order, conflictingOrder };\n }\n}\n\nexport class RenderFeatureStageFailedError extends Error {\n readonly code = 'render-feature-stage-failed' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: RenderFeatureStageFailedDetail;\n\n constructor(\n featureIdentity: string,\n order: number,\n stage: RenderFeatureStage,\n recovery: RenderFeatureRecovery,\n ) {\n const expected = `feature '${featureIdentity}' completes its ${stage} stage without an error`;\n const hint = renderFeatureRecoveryHintByRecovery[recovery](featureIdentity, stage);\n super(`render feature '${featureIdentity}' failed during ${stage}`);\n this.name = 'RenderFeatureStageFailedError';\n this.expected = expected;\n this.hint = hint;\n this.detail = { featureIdentity, order, stage, recovery };\n }\n}\n\nexport class RenderFeatureCapabilityMissingError extends Error {\n readonly code = 'render-feature-capability-missing' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: RenderFeatureCapabilityMissingDetail;\n\n constructor(\n featureIdentity: string,\n order: number,\n capability: RenderFeatureCapabilityMissingDetail['capability'],\n ) {\n const expected = `device capability '${capability}' is available for feature '${featureIdentity}'`;\n const hint = `disable '${featureIdentity}' or use a device with '${capability}' capability`;\n super(`render feature '${featureIdentity}' requires missing capability '${capability}'`);\n this.name = 'RenderFeatureCapabilityMissingError';\n this.expected = expected;\n this.hint = hint;\n this.detail = { featureIdentity, order, capability };\n }\n}\n\nexport class RenderFeaturePassOrderConflictError extends Error {\n readonly code = 'render-feature-pass-order-conflict' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: RenderFeaturePassOrderConflictDetail;\n\n constructor(\n featureIdentity: string,\n order: number,\n passIdentity: string,\n dependencyIdentity: string,\n ) {\n const expected = `feature pass '${passIdentity}' follows dependency '${dependencyIdentity}'`;\n const hint = `reorder '${featureIdentity}' passes so '${passIdentity}' follows '${dependencyIdentity}'`;\n super(`render feature '${featureIdentity}' pass order conflict`);\n this.name = 'RenderFeaturePassOrderConflictError';\n this.expected = expected;\n this.hint = hint;\n this.detail = { featureIdentity, order, passIdentity, dependencyIdentity };\n }\n}\n\nexport class RenderFeaturePreparationFailedError extends Error {\n readonly code = 'render-feature-preparation-failed' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: RenderFeaturePreparationFailedDetail;\n\n constructor(\n featureIdentity: string,\n order: number,\n operation: string,\n resourceKind: RenderFeaturePreparationFailedDetail['resourceKind'],\n resourceName: string,\n reason: string,\n recovery: RenderFeatureRecovery,\n ) {\n const expected = `${resourceKind} '${resourceName}' is prepared during ${operation}`;\n const hint = `repair '${resourceName}' and retry feature '${featureIdentity}' on ${recovery}`;\n super(`render feature '${featureIdentity}' preparation failed for '${resourceName}'`);\n this.name = 'RenderFeaturePreparationFailedError';\n this.expected = expected;\n this.hint = hint;\n this.detail = {\n featureIdentity,\n order,\n stage: 'prepare',\n operation,\n resourceKind,\n resourceName,\n reason,\n recovery,\n };\n }\n}\n\nexport class RenderFeaturePreparedStateMismatchError extends Error {\n readonly code = 'render-feature-prepared-state-mismatch' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: RenderFeaturePreparedStateMismatchDetail;\n\n constructor(detail: RenderFeaturePreparedStateMismatchDetail) {\n const expected = `${detail.resourceKind} state is compatible for '${detail.operation}'`;\n const hint = `repair '${detail.reason}' for feature '${detail.featureIdentity}' and retry`;\n super(`render feature '${detail.featureIdentity}' prepared state mismatch`);\n this.name = 'RenderFeaturePreparedStateMismatchError';\n this.expected = expected;\n this.hint = hint;\n this.detail = detail;\n }\n}\n\nexport class RenderFeatureDrawRecordingFailedError extends Error {\n readonly code = 'render-feature-draw-recording-failed' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: RenderFeatureDrawRecordingFailedDetail;\n\n constructor(\n featureIdentity: string,\n order: number,\n operation: string,\n resourceKind: RenderFeatureDrawRecordingFailedDetail['resourceKind'],\n reason: string,\n backendReason: string,\n recovery: RenderFeatureRecovery,\n ) {\n const expected = `${resourceKind} recording succeeds for '${operation}'`;\n const hint = `repair '${reason}' and retry feature '${featureIdentity}' after ${recovery}`;\n super(`render feature '${featureIdentity}' draw recording failed`);\n this.name = 'RenderFeatureDrawRecordingFailedError';\n this.expected = expected;\n this.hint = hint;\n this.detail = {\n featureIdentity,\n order,\n stage: 'record',\n operation,\n resourceKind,\n reason,\n backendReason,\n recovery,\n };\n }\n}\n\n// ── ObservationUnavailableError ───────────────────────────────────────────\n\nexport type ObservationUnavailableReason =\n | 'no-frame'\n | 'resource'\n | 'copy-src'\n | 'stale'\n | 'identity'\n | 'format'\n | 'readback-failed';\n\nexport interface ObservationUnavailableDetail {\n readonly reason: ObservationUnavailableReason;\n readonly recovery: 'draw-current-frame' | 'enable-copy-src' | 'retry-readback';\n}\n\n/** A producer-owned current-frame observation could not be made available. */\nexport class ObservationUnavailableError extends Error {\n readonly code = 'observation-unavailable' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: ObservationUnavailableDetail;\n\n constructor(reason: ObservationUnavailableReason, hint: string) {\n let recovery: ObservationUnavailableDetail['recovery'];\n if (reason === 'copy-src') recovery = 'enable-copy-src';\n else if (reason === 'resource' || reason === 'readback-failed') recovery = 'retry-readback';\n else recovery = 'draw-current-frame';\n super(`current-frame observation unavailable: ${reason}`);\n this.name = 'ObservationUnavailableError';\n this.expected = 'a fresh producer-owned rgba16float current-frame observation';\n this.hint = hint;\n this.detail = { reason, recovery };\n }\n}\n\nexport type SceneDataUnavailableReason =\n | 'capability-missing'\n | 'producer-missing'\n | 'coverage-incomplete'\n | 'renderer-recovering';\nexport interface SceneDataUnavailableDetail {\n readonly featureIdentity: string;\n readonly schema: SceneDataSchemaId;\n readonly lane: SceneDataLane;\n readonly reason: SceneDataUnavailableReason;\n readonly missingContributorIds: readonly string[];\n readonly omittedMissingContributorCount: number;\n readonly recovery: 'enable-capability' | 'next-frame' | 'renderer-recover';\n}\nexport class SceneDataUnavailableError extends Error {\n readonly code = 'scene-data-unavailable' as const;\n readonly expected = 'the requested semantic scene data is available for the active plan';\n readonly hint: string;\n readonly detail: SceneDataUnavailableDetail;\n constructor(detail: SceneDataUnavailableDetail) {\n const hint =\n detail.recovery === 'enable-capability'\n ? 'enable rgba16floatRenderable and retry the current frame'\n : detail.recovery === 'renderer-recover'\n ? 'wait for renderer recovery, then retry the frame'\n : 'restore the producer coverage and retry on the next frame';\n super(`scene data '${detail.schema}' unavailable for '${detail.featureIdentity}'`);\n this.name = 'SceneDataUnavailableError';\n this.hint = hint;\n this.detail = Object.freeze({\n ...detail,\n missingContributorIds: Object.freeze([...detail.missingContributorIds].slice(0, 32)),\n omittedMissingContributorCount: Math.max(\n detail.omittedMissingContributorCount,\n Math.max(0, detail.missingContributorIds.length - 32),\n ),\n });\n }\n}\n\nexport class TaaUnavailableError extends Error {\n readonly code = 'taa-unavailable' as const;\n readonly expected =\n 'Standard TAA has a renderable rgba16float target and a complete resolve path';\n readonly hint =\n 'enable rgba16float rendering or select none/fxaa explicitly; do not treat TAA as no-AA';\n readonly detail: {\n readonly reason: 'capability' | 'topology' | 'history';\n readonly observed?: string;\n };\n constructor(reason: 'capability' | 'topology' | 'history', observed?: string) {\n super(`taa-unavailable: ${reason}`);\n this.name = 'TaaUnavailableError';\n this.detail = observed === undefined ? { reason } : { reason, observed };\n }\n}\n\nexport interface FrameReceiptStaleDetail {\n readonly frameId: number;\n readonly receiptGeneration: number;\n readonly currentGeneration: number;\n}\n\n/** Receipt-bound observation failed closed at a generation fence. */\nexport class FrameReceiptStaleError extends Error {\n readonly code = 'frame-receipt-stale' as const;\n readonly expected = 'the observation receipt belongs to the active device generation';\n readonly hint = 'draw a new frame and call observe with its returned FrameReceipt';\n readonly detail: FrameReceiptStaleDetail;\n\n constructor(detail: FrameReceiptStaleDetail) {\n super('frame receipt belongs to a retired device generation');\n this.name = 'FrameReceiptStaleError';\n this.detail = detail;\n }\n}\n\nexport interface RendererContractFailureDetail {\n readonly operation: 'construct' | 'attach' | 'draw' | 'observe';\n readonly cause: string;\n}\n\n/** Structured boundary failure while adapting an owner contract. */\nexport class RendererContractFailureError extends Error {\n readonly code = 'renderer-contract-failed' as const;\n readonly expected = 'renderer owner contracts remain valid at the public boundary';\n readonly hint = 'repair the owner contract and retry the operation';\n readonly detail: RendererContractFailureDetail;\n\n constructor(operation: RendererContractFailureDetail['operation'], cause: string) {\n super(`renderer ${operation} contract failed: ${cause}`);\n this.name = 'RendererContractFailureError';\n this.detail = { operation, cause };\n }\n}\n\nexport interface EnvironmentSourceConflictDetail {\n readonly owners: readonly {\n readonly kind: 'image' | 'atmosphere';\n readonly entityKey: number;\n readonly sourceKey: string;\n }[];\n}\n\nexport class EnvironmentSourceConflictError extends Error {\n readonly code = 'environment-source-conflict' as const;\n readonly expected = 'exactly one environment source owns the frame';\n readonly hint = 'remove all but one image or atmosphere environment owner';\n readonly detail: EnvironmentSourceConflictDetail;\n\n constructor(owners: readonly EnvironmentSourceConflictDetail['owners'][number][]) {\n super('environment source owners conflict');\n this.name = 'EnvironmentSourceConflictError';\n this.detail = { owners: owners.map((owner) => Object.freeze({ ...owner })) };\n }\n}\n\nexport interface FogCardinalityDetail {\n readonly count: number;\n}\n\nexport class FogCardinalityError extends Error {\n readonly code = 'fog-cardinality' as const;\n readonly expected = 'zero or one Fog owner contributes to a frame';\n readonly hint = 'remove extra Fog owners so the resource owner has at most one';\n readonly detail: FogCardinalityDetail;\n\n constructor(count: number) {\n super(`Fog owner cardinality is ${count}`);\n this.name = 'FogCardinalityError';\n this.detail = { count };\n }\n}\n\nexport interface TaaCapsInsufficientDetail {\n readonly required: readonly string[];\n readonly available: readonly string[];\n}\n\nexport class TaaCapsInsufficientError extends Error {\n readonly code = 'taa-caps-insufficient' as const;\n readonly expected = 'the backend exposes the capabilities required by TAA';\n readonly hint = 'select a backend with the required TAA capabilities or disable TAA on Camera';\n readonly detail: TaaCapsInsufficientDetail;\n\n constructor(required: readonly string[], available: readonly string[]) {\n super('TAA capabilities are insufficient');\n this.name = 'TaaCapsInsufficientError';\n this.detail = { required: [...required], available: [...available] };\n }\n}\n\nexport interface EnvironmentGenerationFailedDetail {\n readonly sourceKey: string;\n readonly stage: 'prepare' | 'build' | 'execute' | 'finish' | 'submit';\n}\n\nexport class EnvironmentGenerationFailedError extends Error {\n readonly code = 'environment-generation-failed' as const;\n readonly expected = 'the selected environment generation completes its owner stage';\n readonly hint = 'inspect the stage and sourceKey, then retry after correcting the environment';\n readonly detail: EnvironmentGenerationFailedDetail;\n\n constructor(sourceKey: string, stage: EnvironmentGenerationFailedDetail['stage']) {\n super(`environment generation failed during ${stage}`);\n this.name = 'EnvironmentGenerationFailedError';\n this.detail = { sourceKey, stage };\n }\n}\n\nexport interface AtmosphereInvalidParameterDetail {\n readonly field: string;\n readonly value: number;\n}\n\nexport interface AtmosphereParameterRange {\n readonly min: number;\n readonly max: number;\n}\n\nexport class AtmosphereInvalidParameterError extends Error {\n readonly code = 'atmosphere-invalid-parameter' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: AtmosphereInvalidParameterDetail;\n\n constructor(field: string, value: number, range: AtmosphereParameterRange) {\n super(`Atmosphere.${field} is invalid`);\n this.name = 'AtmosphereInvalidParameterError';\n this.detail = { field, value };\n const rangeText = Number.isFinite(range.max)\n ? `[${range.min}, ${range.max}]`\n : `>= ${range.min}`;\n this.expected = `Atmosphere.${field} must be finite and ${rangeText}`;\n this.hint = `set Atmosphere.${field} to a finite value ${rangeText}`;\n }\n}\n\nexport interface OwnerStageFailedDetail {\n readonly owner: 'environment' | 'temporal' | 'fog' | 'renderer';\n readonly stage: 'extract' | 'prepare' | 'record' | 'finish' | 'submit';\n}\n\nexport class OwnerStageFailedError extends Error {\n readonly code = 'owner-stage-failed' as const;\n readonly expected = 'the owner completes its current frame stage';\n readonly hint = 'inspect the owner and stage, keep the last-known-good frame, and retry';\n readonly detail: OwnerStageFailedDetail;\n\n constructor(owner: OwnerStageFailedDetail['owner'], stage: OwnerStageFailedDetail['stage']) {\n super(`${owner} owner failed during ${stage}`);\n this.name = 'OwnerStageFailedError';\n this.detail = { owner, stage };\n }\n}\n\nexport interface RendererOperationCause {\n readonly code: string;\n readonly expected: string;\n readonly hint: string;\n readonly detail?: unknown;\n}\n\nexport interface RendererOperationDetailByCode {\n readonly 'world-lease-invalid': {\n readonly operation: 'attach' | 'draw';\n readonly cause: RendererOperationCause;\n };\n readonly 'frame-input-invalid': {\n readonly operation: 'draw' | 'set-profile';\n readonly cause: RendererOperationCause;\n };\n readonly 'scene-projection-failed': {\n readonly operation: 'draw';\n readonly cause: RendererOperationCause;\n };\n readonly 'asset-binding-failed': {\n readonly operation: 'draw';\n readonly cause: RendererOperationCause;\n };\n readonly 'feature-plan-failed': {\n readonly operation: 'draw';\n readonly cause: RendererOperationCause;\n };\n readonly 'graph-build-failed': {\n readonly operation: 'draw' | 'set-profile';\n readonly cause: RendererOperationCause;\n };\n readonly 'device-operation-failed': {\n readonly operation: 'draw' | 'complete-frame' | 'renderer-event';\n readonly frameId?: number;\n readonly deviceGeneration?: number;\n readonly cause: RendererOperationCause;\n };\n readonly 'surface-unavailable': {\n readonly operation: 'release-surface' | 'restore-surface';\n readonly cause: RendererOperationCause;\n };\n readonly 'renderer-state-invalid': {\n readonly operation: 'draw' | 'set-profile' | 'recover' | 'dispose';\n readonly state: string;\n readonly cause?: RendererOperationCause;\n };\n readonly 'recovery-failed': {\n readonly operation: 'recover';\n readonly phase: RecoveryPhase;\n readonly oldGeneration: number;\n readonly candidateGeneration: number;\n readonly attempt: number;\n readonly elapsedMs: number;\n readonly retryable: boolean;\n readonly guidance: 'retry' | 'repair-owner' | 'rebuild-renderer';\n readonly owner: string;\n readonly resourceKind: string;\n readonly lastOutcome: RecoveryOutcome;\n readonly rehydratedRoots: number;\n readonly staleLossEvents: number;\n readonly cleanupFailures: readonly RendererOperationCause[];\n readonly cause: RendererOperationCause;\n };\n readonly 'cleanup-failed': {\n readonly operation: 'dispose';\n readonly causes: readonly RendererOperationCause[];\n };\n}\n\nexport type RendererOperationErrorCode = keyof RendererOperationDetailByCode;\n\nconst RENDERER_OPERATION_ERROR_POLICY = {\n 'world-lease-invalid': {\n expected: 'every render World is represented by a live lease owned by this Renderer',\n hint: 'attach the World to this Renderer and use the returned lease',\n },\n 'frame-input-invalid': {\n expected: 'the frame input references attached leases and a valid immutable RenderProfile',\n hint: 'repair the frame input and retry draw or setProfile',\n },\n 'scene-projection-failed': {\n expected: 'the attached World projects into the renderer-owned RenderScene',\n hint: 'inspect the structured cause, repair the World publication, and retry draw',\n },\n 'asset-binding-failed': {\n expected: 'all frame assets resolve to valid renderer-owned bindings',\n hint: 'inspect the structured cause, rebuild or cold-cook the asset, and retry draw',\n },\n 'feature-plan-failed': {\n expected: 'every installed RenderFeature produces a valid declarative plan',\n hint: 'inspect the feature cause, repair its plan, and retry draw',\n },\n 'graph-build-failed': {\n expected: 'the Standard graph builds from the active profile and feature plans',\n hint: 'inspect the graph cause, repair the profile or plan, and retry',\n },\n 'device-operation-failed': {\n expected: 'the active device generation completes the renderer-owned operation',\n hint: 'inspect renderer state and the structured cause, then retry or recover',\n },\n 'surface-unavailable': {\n expected: 'the presentation surface accepts the requested lifecycle operation',\n hint: 'inspect renderer state, then restore the surface or create a new Renderer',\n },\n 'renderer-state-invalid': {\n expected: 'the Renderer is in a state that accepts the requested operation',\n hint: 'inspect renderer state and choose retry, restoreSurface, recover, or stop',\n },\n 'recovery-failed': {\n expected: 'one recovery attempt publishes a complete replacement device generation',\n hint: 'inspect the structured cause and retry recover after the host-selected delay',\n },\n 'cleanup-failed': {\n expected: 'Renderer disposal completes every registered cleanup in reverse ownership order',\n hint: 'inspect the ordered cleanup causes; the Renderer remains disposed and must not be reused',\n },\n} as const satisfies Readonly<\n Record<RendererOperationErrorCode, { readonly expected: string; readonly hint: string }>\n>;\n\n/** Public renderer-operation failure with a code-narrowed structured detail. */\nexport class RendererOperationError<Code extends RendererOperationErrorCode> extends Error {\n readonly code: Code;\n readonly expected: string;\n readonly hint: string;\n readonly detail: RendererOperationDetailByCode[Code];\n\n constructor(code: Code, detail: RendererOperationDetailByCode[Code]) {\n const policy = RENDERER_OPERATION_ERROR_POLICY[code];\n super(`${code}: ${policy.expected}`);\n this.name = 'RendererOperationError';\n this.code = code;\n this.expected = policy.expected;\n this.hint = policy.hint;\n this.detail = detail;\n }\n}\n\nexport type RendererExpectedOperationError = {\n readonly [Code in RendererOperationErrorCode]: RendererOperationError<Code>;\n}[RendererOperationErrorCode];\n\n// -- Points/Lines admission errors -------------------------------------------\n\nexport interface PointsLinesInvalidStyleDetail {\n readonly entity: number;\n readonly component: 'Points' | 'Lines' | 'Points/Lines';\n readonly field: string;\n readonly value: number | string | undefined;\n readonly expected: string;\n}\n\nexport class PointsLinesInvalidStyleError extends Error {\n readonly code = 'points-lines-invalid-style' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: PointsLinesInvalidStyleDetail;\n\n constructor(detail: PointsLinesInvalidStyleDetail) {\n super(`invalid ${detail.component} style at ${detail.field}`);\n this.name = 'PointsLinesInvalidStyleError';\n this.expected = detail.expected;\n this.hint = `repair entity ${detail.entity} ${detail.component}.${detail.field} and retry admission`;\n this.detail = detail;\n }\n}\n\nexport interface PointsLinesTopologyMismatchDetail {\n readonly entity: number;\n readonly submesh: number;\n readonly expected: string;\n readonly actual: string;\n}\n\nexport class PointsLinesTopologyMismatchError extends Error {\n readonly code = 'points-lines-topology-mismatch' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: PointsLinesTopologyMismatchDetail;\n\n constructor(detail: PointsLinesTopologyMismatchDetail) {\n super(`Points/Lines topology mismatch at submesh ${detail.submesh}`);\n this.name = 'PointsLinesTopologyMismatchError';\n this.expected = `submesh ${detail.submesh} topology is ${detail.expected}`;\n this.hint = `rebuild entity ${detail.entity} with ${detail.expected} geometry before retrying Points/Lines admission`;\n this.detail = detail;\n }\n}\n\nexport interface PointsLinesStyleUnsupportedDetail {\n readonly lane: string;\n readonly field: string;\n readonly member: string;\n readonly supported: readonly string[];\n}\n\nexport class PointsLinesStyleUnsupportedError extends Error {\n readonly code = 'points-lines-style-unsupported' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: PointsLinesStyleUnsupportedDetail;\n\n constructor(detail: PointsLinesStyleUnsupportedDetail) {\n super(`unsupported Points/Lines ${detail.field} member ${detail.member}`);\n this.name = 'PointsLinesStyleUnsupportedError';\n this.expected = `${detail.field} is one of ${detail.supported.join(', ')}`;\n this.hint = `use a supported Points/Lines ${detail.field} member or wait for a later milestone`;\n this.detail = detail;\n }\n}\n\nexport interface PointsLinesMaterialUnsupportedDetail {\n readonly entity: number;\n readonly material: string;\n readonly pass: string;\n readonly module: string;\n readonly reason: string;\n}\n\nexport class PointsLinesMaterialUnsupportedError extends Error {\n readonly code = 'points-lines-material-unsupported' as const;\n readonly expected = 'one engine-owned unlit forward MaterialAsset pass';\n readonly hint: string;\n readonly detail: PointsLinesMaterialUnsupportedDetail;\n\n constructor(detail: PointsLinesMaterialUnsupportedDetail) {\n super(`Points/Lines material is unsupported on entity ${detail.entity}`);\n this.name = 'PointsLinesMaterialUnsupportedError';\n this.hint = `use Materials.unlit without a shadow-caster pass for entity ${detail.entity}`;\n this.detail = detail;\n }\n}\n\nexport interface PointsLinesBudgetExceededDetail {\n readonly lane: string;\n readonly requested: number;\n readonly limit: number;\n readonly unit: 'points' | 'segments' | 'vertices' | 'indices' | 'bytes' | 'draws';\n}\n\nexport class PointsLinesBudgetExceededError extends Error {\n readonly code = 'points-lines-budget-exceeded' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: PointsLinesBudgetExceededDetail;\n\n constructor(detail: PointsLinesBudgetExceededDetail) {\n super(`Points/Lines ${detail.unit} budget exceeded`);\n this.name = 'PointsLinesBudgetExceededError';\n this.expected = `${detail.unit} <= ${detail.limit}`;\n this.hint = `reduce Points/Lines ${detail.unit} or split the entity into bounded equivalent batches`;\n this.detail = detail;\n }\n}\n\nexport interface PointsLinesPrepareFailedDetail {\n readonly owner: string;\n readonly generation: number;\n readonly stage: 'prepare';\n readonly cause: string;\n readonly lastKnownGood: boolean;\n}\n\nexport class PointsLinesPrepareFailedError extends Error {\n readonly code = 'points-lines-prepare-failed' as const;\n readonly expected = 'the complete Points/Lines candidate validates before publication';\n readonly hint: string;\n readonly detail: PointsLinesPrepareFailedDetail;\n\n constructor(detail: PointsLinesPrepareFailedDetail) {\n super(`Points/Lines prepare failed at generation ${detail.generation}`);\n this.name = 'PointsLinesPrepareFailedError';\n this.hint = detail.lastKnownGood\n ? 'retain the last known good candidate, repair the producer, and retry prepare'\n : 'repair the producer and retry prepare; the failed first candidate produces zero draw';\n this.detail = detail;\n }\n}\n\n// -- RenderTarget errors ------------------------------------------------------\n\nexport interface RenderTargetDescriptorInvalidDetail {\n readonly field: string;\n readonly value: unknown;\n readonly expected: string;\n}\n\nexport class RenderTargetDescriptorInvalidError extends Error {\n readonly code = 'render-target-descriptor-invalid' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: RenderTargetDescriptorInvalidDetail;\n\n constructor(detail: RenderTargetDescriptorInvalidDetail) {\n super(`render-target-descriptor-invalid: ${detail.field} does not satisfy ${detail.expected}`);\n this.name = 'RenderTargetDescriptorInvalidError';\n this.expected = detail.expected;\n this.hint = `set RenderTargetDescriptor.${detail.field} to the expected value, then retry create or resize`;\n this.detail = detail;\n }\n}\n\nexport interface RenderTargetCapabilityMissingDetail {\n readonly operation: 'create' | 'resize' | 'source' | 'readback';\n readonly requested: string;\n readonly capability: string;\n readonly actual: string;\n}\n\nexport class RenderTargetCapabilityMissingError extends Error {\n readonly code = 'render-target-capability-missing' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: RenderTargetCapabilityMissingDetail;\n\n constructor(detail: RenderTargetCapabilityMissingDetail) {\n super(\n `render-target-capability-missing: ${detail.capability} does not admit ${detail.requested}`,\n );\n this.name = 'RenderTargetCapabilityMissingError';\n this.expected = `${detail.capability} admits ${detail.requested}`;\n this.hint = `choose an admitted target descriptor or use a backend providing ${detail.capability}`;\n this.detail = detail;\n }\n}\n\nexport type RenderTargetStateInvalidReason =\n | 'foreign-renderer'\n | 'destroyed'\n | 'uninitialized'\n | 'generation-mismatch'\n | 'readback-without-intent';\n\nexport interface RenderTargetStateInvalidDetail {\n readonly operation: 'inspect' | 'resize' | 'source' | 'readback' | 'destroy';\n readonly reason: RenderTargetStateInvalidReason;\n readonly state: 'uninitialized' | 'candidate' | 'active' | 'rebuilding' | 'destroyed';\n readonly generation: number;\n}\n\nexport class RenderTargetStateInvalidError extends Error {\n readonly code = 'render-target-state-invalid' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: RenderTargetStateInvalidDetail;\n\n constructor(detail: RenderTargetStateInvalidDetail) {\n super(`render-target-state-invalid: ${detail.operation} cannot use ${detail.reason}`);\n this.name = 'RenderTargetStateInvalidError';\n this.expected = `target state permits ${detail.operation}`;\n this.hint =\n 'use the Renderer that created the target, then initialize, recover, or stop using the destroyed token';\n this.detail = detail;\n }\n}\n\nexport interface RenderTargetOperationFailedDetail {\n readonly operation: 'create' | 'resize' | 'source' | 'readback' | 'destroy' | 'recover';\n readonly stage: 'allocation' | 'compile' | 'write' | 'submit' | 'copy' | 'retire';\n readonly generation: number;\n readonly cause: unknown;\n readonly recovery: 'retry' | 'recover' | 'retain-last-known-good';\n}\n\nexport class RenderTargetOperationFailedError extends Error {\n readonly code = 'render-target-operation-failed' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: RenderTargetOperationFailedDetail;\n\n constructor(detail: RenderTargetOperationFailedDetail) {\n super(`render-target-operation-failed: ${detail.operation} failed during ${detail.stage}`);\n this.name = 'RenderTargetOperationFailedError';\n this.expected = `${detail.operation} completes ${detail.stage}`;\n this.hint =\n 'inspect detail.cause, then retry, recover the Renderer, or retain the last-known-good generation';\n this.detail = detail;\n }\n}\n\nexport interface ReflectionProbeBudgetExceededDetail {\n readonly actual: number;\n readonly budget: number;\n}\n\nexport class ReflectionProbeBudgetExceededError extends Error {\n readonly code = 'reflection-probe-budget-exceeded' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: ReflectionProbeBudgetExceededDetail;\n\n constructor(actual: number, budget: number) {\n super(`reflection-probe-budget-exceeded: ${actual} > ${budget}`);\n this.name = 'ReflectionProbeBudgetExceededError';\n this.expected = `reflection probe work <= ${budget}`;\n this.hint = 'reduce probe updates for this frame or raise the RenderProfile probe budget';\n this.detail = { actual, budget };\n }\n}\n\nexport interface RenderIntentInvalidDetail {\n readonly component: 'CubeCamera' | 'ReflectionProbe';\n readonly field: 'updateIntent';\n readonly value: number;\n readonly allowed: readonly [0, 1, 2];\n}\n\nexport class RenderIntentInvalidError extends Error {\n readonly code = 'render-intent-invalid' as const;\n readonly expected: string;\n readonly hint: string;\n readonly detail: RenderIntentInvalidDetail;\n\n constructor(component: RenderIntentInvalidDetail['component'], value: number) {\n super(`render-intent-invalid: ${component}.updateIntent is not an admitted value`);\n this.name = 'RenderIntentInvalidError';\n this.expected = `${component}.updateIntent is one of 0, 1, or 2`;\n this.hint = `set ${component}.updateIntent to 0, 1, or 2`;\n this.detail = { component, field: 'updateIntent', value, allowed: [0, 1, 2] };\n }\n}\n\nexport interface VolumeOwnerConflictDetail {\n readonly ownerCount: number;\n}\n\nexport class VolumeOwnerConflictError extends Error {\n readonly code = 'volume-owner-conflict' as const;\n readonly expected = 'exactly one global VolumetricFog owner is authored';\n readonly hint = 'remove additional VolumetricFog owners and retry extraction';\n readonly detail: VolumeOwnerConflictDetail;\n\n constructor(ownerCount: number) {\n super(`volume-owner-conflict: received ${ownerCount} owners`);\n this.name = 'VolumeOwnerConflictError';\n this.detail = { ownerCount };\n }\n}\n\nexport interface VolumeDensityShapeMismatchDetail {\n readonly guid: string;\n readonly viewDimension: string;\n}\n\nexport class VolumeDensityShapeMismatchError extends Error {\n readonly code = 'volume-density-shape-mismatch' as const;\n readonly expected = 'density is a linear 3D TextureAsset';\n readonly hint = 'bind a verified linear texture with viewDimension 3d';\n readonly detail: VolumeDensityShapeMismatchDetail;\n\n constructor(guid: string, viewDimension: string) {\n super(`volume-density-shape-mismatch: ${viewDimension} density is not 3d`);\n this.name = 'VolumeDensityShapeMismatchError';\n this.detail = { guid, viewDimension };\n }\n}\n\nexport interface VolumeInvalidBoundsDetail {\n readonly min: readonly [number, number, number];\n readonly max: readonly [number, number, number];\n}\n\nexport class VolumeInvalidBoundsError extends Error {\n readonly code = 'volume-invalid-bounds' as const;\n readonly expected = 'bounds are finite and max is greater than min on every axis';\n readonly hint = 'set finite non-degenerate volume bounds';\n readonly detail: VolumeInvalidBoundsDetail;\n\n constructor(bounds: VolumeInvalidBoundsDetail) {\n super('volume-invalid-bounds: bounds must be finite and non-degenerate');\n this.name = 'VolumeInvalidBoundsError';\n this.detail = bounds;\n }\n}\n\nexport interface VolumeInvalidParametersDetail {\n readonly field: string;\n readonly value: unknown;\n}\n\nexport class VolumeInvalidParametersError extends Error {\n readonly code = 'volume-invalid-parameters' as const;\n readonly expected = 'volume parameters remain finite and inside their closed ranges';\n readonly hint = 'repair extinction, albedo, emission, anisotropy, or maxDistance';\n readonly detail: VolumeInvalidParametersDetail;\n\n constructor(input: { readonly maxDistance?: number; readonly anisotropy?: number }) {\n const field =\n input.maxDistance !== undefined && input.maxDistance <= 0 ? 'maxDistance' : 'parameters';\n const value = field === 'maxDistance' ? input.maxDistance : input.anisotropy;\n super(`volume-invalid-parameters: ${field} is outside the authored range`);\n this.name = 'VolumeInvalidParametersError';\n this.detail = { field, value };\n }\n}\n\nexport type VolumeError =\n | VolumeOwnerConflictError\n | VolumeDensityShapeMismatchError\n | VolumeInvalidBoundsError\n | VolumeInvalidParametersError;\n\nexport interface ProjectorBindingDetail {\n readonly guid: string;\n readonly status: 'pending' | 'invalid' | 'bind-failed';\n}\n\nexport class ProjectorBindingError extends Error {\n readonly code = 'projector-binding-failed' as const;\n readonly expected = 'authored projector is accepted and bound for both surface and volume';\n readonly hint =\n 'inspect the projector Meta/Pack receipt, repair the source, and retry with the same GUID';\n readonly detail: ProjectorBindingDetail;\n\n constructor(guid: string, status: ProjectorBindingDetail['status']) {\n super(`projector binding failed for ${guid}: ${status}`);\n this.name = 'ProjectorBindingError';\n this.detail = { guid, status };\n }\n}\n\n// -- RenderErrorCode / RenderError closed unions --------------------------------\n\n/**\n * Closed union of render-cluster error codes. AI users perform exhaustive\n * `switch (err.code)` without default; TS guards completeness.\n */\nexport type RenderErrorCode = RenderError['code'];\n\n/**\n * Closed union of the render-cluster structured error classes, each carrying a\n * `RenderErrorCode` discriminant on `.code`.\n */\nexport type RenderError =\n | LifecycleConstructionError\n | RendererExpectedOperationError\n | FrameReceiptStaleError\n | RendererContractFailureError\n | ObservationUnavailableError\n | SceneDataUnavailableError\n | TaaUnavailableError\n | ShadowInvalidConfigError\n | EquirectProjectionFailedError\n | StandardLightBudgetExceededError\n | StandardClusterIndexOverflowError\n | StandardClusterTransportUnavailableError\n | StandardProfileInvalidError\n | PointShadowAtlasUninitializedError\n | PointShadowAtlasBoundsViolationError\n | VideoUploadUnsupportedError\n | VertexStorageBufferUnavailableError\n | VertexColorVariantConflictError\n | SkinPaletteOverflowError\n | SkinMaterialMismatchError\n | MaterialSkinAttrMissingError\n | TransmissionCapabilityMissingError\n | RenderFeatureRegistrationConflictError\n | RenderFeatureStageFailedError\n | RenderFeatureCapabilityMissingError\n | RenderFeaturePassOrderConflictError\n | RenderFeaturePreparationFailedError\n | RenderFeaturePreparedStateMismatchError\n | RenderFeatureDrawRecordingFailedError\n | EnvironmentSourceConflictError\n | FogCardinalityError\n | TaaCapsInsufficientError\n | EnvironmentGenerationFailedError\n | AtmosphereInvalidParameterError\n | OwnerStageFailedError\n | PointsLinesInvalidStyleError\n | PointsLinesTopologyMismatchError\n | PointsLinesStyleUnsupportedError\n | PointsLinesMaterialUnsupportedError\n | PointsLinesBudgetExceededError\n | PointsLinesPrepareFailedError\n | LightResourceUnavailableError\n | RenderTargetDescriptorInvalidError\n | RenderTargetCapabilityMissingError\n | RenderTargetStateInvalidError\n | RenderTargetOperationFailedError\n | ReflectionProbeBudgetExceededError\n | RenderIntentInvalidError\n | ProjectorBindingError\n | VolumeError;\n","/**\n * Public prepared-graphics vocabulary for producer-owned RenderFeatures.\n *\n * The five prepared kinds are declarative references only: the render owner\n * retains device, resource, graph, recording, and submission ownership.\n */\n\nimport type { TextureFormat } from '@forgeax/engine-rhi';\nimport {\n err,\n type MaterialRenderState,\n ok,\n type PrimitiveTopology,\n type Result,\n} from '@forgeax/engine-types';\nimport {\n type RenderError,\n RenderFeaturePreparationFailedError,\n type RenderFeaturePreparedStateMismatchDetail,\n RenderFeaturePreparedStateMismatchError,\n} from '../errors/render';\nimport type { SceneDataTarget } from '../temporal/scene-data';\nimport type { RenderFeatureGpuBufferRef } from './prepared-gpu-work';\nimport type { RenderFeatureTargetHandle } from './targets';\nimport type { PreparedKind } from './vocabulary';\n\n/** Closed prepared kinds: pipeline, bindings, vertex/index data, and attachment. */\nexport type { PreparedKind } from './vocabulary';\n\n/** Canonical vertex layouts owned by the prepared-graphics host. */\nexport const RENDER_FEATURE_VERTEX_LAYOUTS = Object.freeze({\n positionSizeColorInstance: 'position-size-color-instance',\n billboardMaterialInstance: 'billboard-material-instance',\n topologySegmentInstance: 'topology-segment-instance',\n meshGeometryMaterialInstance: 'mesh-geometry-material-instance',\n} as const);\n\n/**\n * Opaque render-owned state identified by its prepared kind and device generation.\n * A generation change invalidates old references after device recovery or\n * pipeline replacement; features never construct or inspect backend handles.\n * Features may pass this reference back to the render owner but do not receive a\n * device, encoder, backend handle, or submit authority.\n */\nexport interface RenderFeaturePreparedRef<Kind extends PreparedKind = PreparedKind> {\n readonly kind: Kind;\n readonly generation: number;\n}\n\n/** Declarative request for a registered graphics pipeline. */\nexport interface RenderFeaturePipelineDescriptor {\n readonly shader: string;\n readonly vertexLayout: string;\n readonly colorFormats: readonly TextureFormat[];\n readonly depthFormat?: TextureFormat;\n /** Sample count of the target this pipeline will draw into. */\n readonly sampleCount?: 1 | 4;\n /** Primitive topology consumed by the prepared draw. */\n readonly topology?: PrimitiveTopology;\n /** Index scalar format when the topology consumes an index buffer. */\n readonly indexFormat?: 'uint16' | 'uint32';\n /**\n * Declarative raster/depth/blend overrides for this pipeline. The render\n * owner maps this portable material state onto the backend pipeline; a\n * feature never receives a backend pipeline descriptor or device handle.\n */\n readonly renderState?: MaterialRenderState;\n}\n\n/** Declarative request for values bound through a prepared pipeline. */\nexport interface RenderFeatureBindingsDescriptor {\n readonly pipeline: RenderFeaturePreparedRef<'pipeline'>;\n readonly values: Readonly<Record<string, unknown>> & {\n readonly group?: number;\n readonly sceneDepth?: RenderFeatureTargetHandle;\n /** Binding slot for a view-plus-scene-depth group (0 keeps legacy behavior). */\n readonly sceneDepthBinding?: number;\n };\n}\n\n/** CPU-owned vertex data and its canonical layout identity. */\nexport type RenderFeatureVertexDataDescriptor =\n | {\n readonly layout: string;\n readonly data: ArrayBufferView | readonly number[];\n readonly buffer?: never;\n }\n | {\n readonly layout: string;\n readonly buffer: RenderFeatureGpuBufferRef;\n readonly data?: never;\n };\n\n/** CPU-owned or persistent GPU-owned index data and its scalar format. */\nexport type RenderFeatureIndexDataDescriptor =\n | {\n readonly format: 'uint16' | 'uint32';\n readonly data: Uint16Array | Uint32Array;\n readonly buffer?: never;\n }\n | {\n readonly format: 'uint16' | 'uint32';\n readonly buffer: RenderFeatureGpuBufferRef;\n readonly data?: never;\n };\n\n/**\n * Feature-facing preparation facade. Call these methods during `prepare`, then\n * pass the returned references to `addGraphicsPass` during `contribute`; the\n * render owner retains resource, graph, recording, and submission ownership.\n */\nexport interface RenderFeatureGraphicsPrepare {\n /** Prepare a registered graphics pipeline without exposing backend state. */\n preparePipeline(\n name: string,\n descriptor: RenderFeaturePipelineDescriptor,\n ): Result<RenderFeaturePreparedRef<'pipeline'>, RenderError>;\n /** Prepare bindings compatible with a prepared pipeline. */\n prepareBindings(\n name: string,\n descriptor: RenderFeatureBindingsDescriptor,\n ): Result<RenderFeaturePreparedRef<'bindings'>, RenderError>;\n /** Prepare vertex data using a canonical layout identity. */\n prepareVertexData(\n name: string,\n descriptor: RenderFeatureVertexDataDescriptor,\n ): Result<RenderFeaturePreparedRef<'vertex-data'>, RenderError>;\n /** Prepare index data for an indexed draw record. */\n prepareIndexData(\n name: string,\n descriptor: RenderFeatureIndexDataDescriptor,\n ): Result<RenderFeaturePreparedRef<'index-data'>, RenderError>;\n}\n\n/** A color target declared by a graphics pass. */\nexport interface RenderFeatureColorAttachment {\n readonly resource: string | RenderFeatureTargetHandle;\n readonly format: TextureFormat;\n readonly loadOp: 'load' | 'clear';\n readonly storeOp: 'store' | 'discard';\n}\n\n/** A depth/stencil target declared by a graphics pass. */\nexport interface RenderFeatureDepthStencilAttachment {\n readonly resource: string | RenderFeatureTargetHandle;\n readonly format: TextureFormat;\n readonly depthLoadOp: 'load' | 'clear';\n readonly depthStoreOp: 'store' | 'discard';\n}\n\n/** The attachments a graphics pass requires from the render owner. */\nexport interface RenderFeatureGraphicsPassAttachments {\n readonly colors: readonly RenderFeatureColorAttachment[];\n readonly depthStencil?: RenderFeatureDepthStencilAttachment;\n}\n\n/** One vertex slot consumed by a declarative draw record. */\nexport interface RenderFeatureVertexDataBinding {\n readonly slot: number;\n readonly resource: RenderFeaturePreparedRef<'vertex-data'>;\n}\n\n/** Non-indexed draw command. */\nexport interface RenderFeatureDrawCommand {\n readonly vertexCount: number;\n readonly instanceCount: number;\n readonly firstVertex?: number;\n readonly firstInstance?: number;\n}\n\n/** Indexed draw command. */\nexport interface RenderFeatureIndexedDrawCommand {\n readonly indexCount: number;\n readonly instanceCount: number;\n readonly firstIndex?: number;\n readonly baseVertex?: number;\n readonly firstInstance?: number;\n}\n\nexport interface RenderFeatureIndirectDrawCommand {\n readonly buffer: RenderFeatureGpuBufferRef;\n readonly offset?: number;\n}\n\n/** Index state attached to an indexed draw record. */\nexport interface RenderFeatureIndexDataBinding {\n readonly resource: RenderFeaturePreparedRef<'index-data'>;\n readonly format: 'uint16' | 'uint32';\n}\n\n/** The two supported graphics draw record shapes: vertex-only and indexed. */\nexport type RenderFeatureDrawRecord =\n | {\n readonly kind: 'draw';\n readonly pipeline: RenderFeaturePreparedRef<'pipeline'>;\n readonly bindings: readonly RenderFeaturePreparedRef<'bindings'>[];\n readonly vertexData: readonly RenderFeatureVertexDataBinding[];\n /** Explicit fullscreen contract: the vertex shader owns vertex_index. */\n readonly vertexLayout?: 'none';\n readonly indexData?: RenderFeatureIndexDataBinding;\n readonly command: RenderFeatureDrawCommand;\n }\n | {\n readonly kind: 'draw-indirect';\n readonly pipeline: RenderFeaturePreparedRef<'pipeline'>;\n readonly bindings: readonly RenderFeaturePreparedRef<'bindings'>[];\n readonly vertexData: readonly RenderFeatureVertexDataBinding[];\n readonly vertexLayout?: 'none';\n readonly indexData?: RenderFeatureIndexDataBinding;\n readonly command: RenderFeatureIndirectDrawCommand;\n }\n | {\n readonly kind: 'draw-indexed';\n readonly pipeline: RenderFeaturePreparedRef<'pipeline'>;\n readonly bindings: readonly RenderFeaturePreparedRef<'bindings'>[];\n readonly vertexData: readonly RenderFeatureVertexDataBinding[];\n readonly vertexLayout?: 'none';\n readonly indexData: RenderFeatureIndexDataBinding | undefined;\n readonly command: RenderFeatureIndexedDrawCommand;\n }\n | {\n readonly kind: 'draw-indexed-indirect';\n readonly pipeline: RenderFeaturePreparedRef<'pipeline'>;\n readonly bindings: readonly RenderFeaturePreparedRef<'bindings'>[];\n readonly vertexData: readonly RenderFeatureVertexDataBinding[];\n readonly vertexLayout?: 'none';\n readonly indexData: RenderFeatureIndexDataBinding | undefined;\n readonly command: RenderFeatureIndirectDrawCommand;\n };\n\n/**\n * Declaration submitted to the existing graph-owned contribution staging.\n * This is a graphics extension of graph-only `addPass`, not a second graph.\n */\nexport interface RenderFeatureGraphicsPassDescriptor {\n readonly attachments: RenderFeatureGraphicsPassAttachments;\n /** Targets sampled by shaders but not attached for writing in this pass. */\n readonly sampledTargets?: readonly (RenderFeatureTargetHandle | SceneDataTarget)[];\n readonly draws: readonly RenderFeatureDrawRecord[];\n}\n\n/**\n * Prepared state projected by the render owner for pure descriptor validation.\n * The generation and opaque references are host facts, not producer-owned GPU\n * state.\n */\nexport interface RenderFeaturePreparedGraphicsState {\n readonly capabilityAvailable: boolean;\n readonly generation: number;\n readonly attachments: readonly {\n readonly resource: string | RenderFeatureTargetHandle;\n readonly format: TextureFormat;\n }[];\n readonly pipeline: RenderFeaturePreparedRef | undefined;\n /** All prepared pipelines available to the current graphics pass. */\n readonly pipelines?: readonly RenderFeaturePreparedRef[];\n readonly bindings: readonly RenderFeaturePreparedRef[];\n readonly vertexData: readonly RenderFeaturePreparedRef[];\n readonly indexData: readonly RenderFeaturePreparedRef[];\n}\n\n/** Successful validation result consumed by the render host projector. */\nexport interface RenderFeatureValidatedGraphicsPass {\n readonly acceptedDrawCount: number;\n}\n\nfunction invalid(\n featureIdentity: string,\n stage: 'prepare' | 'contribute',\n): Result<never, RenderError> {\n if (stage === 'prepare') {\n return err(\n new RenderFeaturePreparationFailedError(\n featureIdentity,\n -1,\n 'validate-prepared-state',\n 'pipeline',\n 'graphics-state',\n 'prepared-state-unavailable',\n 'next-frame',\n ),\n );\n }\n const detail: RenderFeaturePreparedStateMismatchDetail = {\n featureIdentity,\n order: -1,\n stage: 'contribute',\n operation: 'validate-graphics-pass',\n resourceKind: 'pipeline',\n reason: 'missing-prepared-state',\n missingResource: 'compatible-prepared-state',\n recovery: 'next-frame',\n };\n return err(new RenderFeaturePreparedStateMismatchError(detail));\n}\n\nfunction validRef<Kind extends PreparedKind>(\n reference: RenderFeaturePreparedRef<Kind>,\n kind: Kind,\n generation: number,\n): boolean {\n return reference.kind === kind && reference.generation === generation;\n}\n\nfunction hasAttachment(\n available: RenderFeaturePreparedGraphicsState['attachments'],\n required: RenderFeatureColorAttachment | RenderFeatureDepthStencilAttachment,\n): boolean {\n const identity = (resource: string | RenderFeatureTargetHandle): string =>\n typeof resource === 'string'\n ? `local:${resource}`\n : `pipeline:${resource.kind}:${resource.format}:${resource.sampleCount}`;\n const requiredResource = identity(required.resource);\n return available.some(\n (attachment) =>\n identity(attachment.resource) === requiredResource && attachment.format === required.format,\n );\n}\n\nfunction hasPreparedRef(\n available: readonly RenderFeaturePreparedRef[],\n required: RenderFeaturePreparedRef,\n): boolean {\n return available.some((reference) => reference === required);\n}\n\nfunction hasValidVertexContract(\n draw: RenderFeatureDrawRecord,\n state: RenderFeaturePreparedGraphicsState,\n): boolean {\n if (draw.vertexLayout === 'none') {\n return draw.kind === 'draw' && draw.vertexData.length === 0;\n }\n return (\n draw.vertexData.length > 0 &&\n draw.vertexData.every(\n (binding) =>\n validRef(binding.resource, 'vertex-data', state.generation) &&\n hasPreparedRef(state.vertexData, binding.resource),\n )\n );\n}\n\nfunction hasValidBindings(\n draw: RenderFeatureDrawRecord,\n state: RenderFeaturePreparedGraphicsState,\n): boolean {\n return (\n draw.bindings.length > 0 &&\n draw.bindings.every(\n (reference) =>\n validRef(reference, 'bindings', state.generation) &&\n hasPreparedRef(state.bindings, reference),\n )\n );\n}\n\n/** Validate a graphics declaration without touching an RHI backend. */\nexport function validateRenderFeatureGraphicsPass(\n featureIdentity: string,\n descriptor: RenderFeatureGraphicsPassDescriptor,\n state: RenderFeaturePreparedGraphicsState,\n): Result<RenderFeatureValidatedGraphicsPass, RenderError> {\n if (!state.capabilityAvailable) return invalid(featureIdentity, 'prepare');\n const pipelines = state.pipelines ?? (state.pipeline === undefined ? [] : [state.pipeline]);\n const hasVertexDraw = descriptor.draws.some((draw) => draw.vertexData.length > 0);\n if (\n pipelines.length === 0 ||\n state.bindings.length === 0 ||\n (hasVertexDraw && state.vertexData.length === 0)\n ) {\n return invalid(featureIdentity, 'prepare');\n }\n if (\n pipelines.some((reference) => !validRef(reference, 'pipeline', state.generation)) ||\n state.bindings.some((reference) => !validRef(reference, 'bindings', state.generation)) ||\n state.vertexData.some((reference) => !validRef(reference, 'vertex-data', state.generation)) ||\n state.indexData.some((reference) => !validRef(reference, 'index-data', state.generation))\n ) {\n return invalid(featureIdentity, 'contribute');\n }\n if (\n descriptor.attachments.colors.some(\n (attachment) => !hasAttachment(state.attachments, attachment),\n ) ||\n (descriptor.attachments.depthStencil !== undefined &&\n !hasAttachment(state.attachments, descriptor.attachments.depthStencil))\n ) {\n return invalid(featureIdentity, 'contribute');\n }\n\n for (const draw of descriptor.draws) {\n if (\n !validRef(draw.pipeline, 'pipeline', state.generation) ||\n !hasPreparedRef(pipelines, draw.pipeline) ||\n !hasValidBindings(draw, state) ||\n !hasValidVertexContract(draw, state)\n ) {\n return invalid(featureIdentity, 'contribute');\n }\n if (\n (draw.kind === 'draw-indirect' || draw.kind === 'draw-indexed-indirect') &&\n draw.command.buffer.generation !== state.generation\n ) {\n return invalid(featureIdentity, 'contribute');\n }\n if (draw.kind === 'draw-indexed' || draw.kind === 'draw-indexed-indirect') {\n if (\n draw.indexData === undefined ||\n !validRef(draw.indexData.resource, 'index-data', state.generation) ||\n !hasPreparedRef(state.indexData, draw.indexData.resource) ||\n state.indexData.length === 0\n ) {\n return invalid(featureIdentity, 'contribute');\n }\n } else if (draw.indexData !== undefined) {\n return invalid(featureIdentity, 'contribute');\n }\n }\n return ok({ acceptedDrawCount: descriptor.draws.length });\n}\n","import type { RenderFeatureMaterialShaderBindingContract } from '@forgeax/engine-render';\nimport {\n err,\n type MaterialAsset,\n type MaterialRenderState,\n type MeshAsset,\n ok,\n type Result,\n} from '@forgeax/engine-types';\nimport type { ParticleRendererSource } from '@forgeax/engine-vfx';\n\ntype ParticleRendererKind = ParticleRendererSource['kind'];\ntype ParticleTopologyRenderer = Extract<ParticleRendererSource, { readonly capacity: number }>;\ntype ParticleTopologyKind = ParticleTopologyRenderer['kind'];\n\nexport const PARTICLE_SHADER_IDENTIFIERS = Object.freeze({\n billboard: 'forgeax::vfx-render.particles.billboard',\n mesh: 'forgeax::vfx-render.particles.mesh',\n ribbon: 'forgeax::vfx-render.particles.ribbon',\n trail: 'forgeax::vfx-render.particles.trail',\n beam: 'forgeax::vfx-render.particles.beam',\n});\n\nexport interface TopologyResourcePlan {\n readonly topology: ParticleTopologyKind;\n readonly capacity: number;\n readonly vertexBytes: number;\n readonly indexBytes: number;\n readonly indirectBytes: number;\n readonly resourceKey: string;\n readonly historyLength?: number;\n readonly stripKey?: 'alive-index';\n readonly endpointField?: 'velocity';\n}\n\nexport interface TopologyResourceError {\n readonly code: 'vfx-topology-resource-invalid';\n readonly expected: string;\n readonly hint: string;\n readonly detail: { readonly path: string };\n}\n\nexport function createTopologyResourcePlan(\n renderer: unknown,\n): Result<TopologyResourcePlan, TopologyResourceError> {\n if (renderer === null || typeof renderer !== 'object' || Array.isArray(renderer))\n return err({\n code: 'vfx-topology-resource-invalid',\n expected: 'a topology renderer object',\n hint: 'declare a ribbon, trail, or beam renderer',\n detail: { path: 'renderer' },\n });\n const value = renderer as Partial<ParticleRendererSource> & Record<string, unknown>;\n if (value.kind !== 'ribbon' && value.kind !== 'trail' && value.kind !== 'beam')\n return err({\n code: 'vfx-topology-resource-invalid',\n expected: 'ribbon, trail, or beam',\n hint: 'do not alias topology output to billboard or mesh',\n detail: { path: 'renderer.kind' },\n });\n if (\n typeof value.capacity !== 'number' ||\n !Number.isInteger(value.capacity) ||\n value.capacity <= 0 ||\n value.capacity > 65536\n )\n return err({\n code: 'vfx-topology-resource-invalid',\n expected: 'capacity in the range 1..65536',\n hint: 'bound topology resources before allocating them',\n detail: { path: 'renderer.capacity' },\n });\n const capacity = value.capacity;\n if (value.kind === 'ribbon' && value.stripKey !== 'alive-index')\n return err({\n code: 'vfx-topology-resource-invalid',\n expected: \"stripKey 'alive-index'\",\n hint: 'use the managed alive-list order until a custom WGSL topology stage owns grouping',\n detail: { path: 'renderer.stripKey' },\n });\n if (\n value.kind === 'trail' &&\n (typeof value.historyLength !== 'number' ||\n !Number.isInteger(value.historyLength) ||\n value.historyLength <= 0 ||\n value.historyLength > 256)\n )\n return err({\n code: 'vfx-topology-resource-invalid',\n expected: 'historyLength in the range 1..256',\n hint: 'bound trail history storage',\n detail: { path: 'renderer.historyLength' },\n });\n if (value.kind === 'beam' && value.endpointField !== 'velocity')\n return err({\n code: 'vfx-topology-resource-invalid',\n expected: \"endpointField 'velocity'\",\n hint: 'use the managed velocity endpoint until a custom WGSL topology stage owns endpoints',\n detail: { path: 'renderer.endpointField' },\n });\n const vertexStride = 12 * 4;\n const segments =\n value.kind === 'trail' ? capacity * Math.max(1, (value.historyLength as number) - 1) : capacity;\n return ok({\n topology: value.kind,\n capacity,\n vertexBytes: Math.max(vertexStride, segments * vertexStride),\n indexBytes: 0,\n indirectBytes: 20,\n resourceKey: `vfx-topology-${value.kind}`,\n ...(value.kind === 'ribbon' ? { stripKey: 'alive-index' as const } : {}),\n ...(value.kind === 'trail' ? { historyLength: value.historyLength as number } : {}),\n ...(value.kind === 'beam' ? { endpointField: 'velocity' as const } : {}),\n });\n}\n\nexport interface TopologyCapacityInput {\n readonly requested: number;\n readonly produced: number;\n readonly degenerate?: number;\n}\n\nexport function topologyCapacitySnapshot(plan: TopologyResourcePlan, input: TopologyCapacityInput) {\n const produced = Math.max(0, Math.min(plan.capacity, input.produced));\n const requested = Math.max(0, input.requested);\n return {\n topology: plan.topology,\n capacity: plan.capacity,\n produced,\n dropped: Math.max(0, requested - produced),\n overflow: Math.max(0, requested - plan.capacity),\n degenerate: Math.max(0, input.degenerate ?? 0),\n } as const;\n}\n\nexport interface ParticleMaterialPass {\n readonly shader: string;\n readonly renderState?: MaterialRenderState;\n}\n\ntype ParticleBlendMode = Extract<ParticleRendererSource, { readonly kind: 'billboard' }>['blend'];\n\nconst PARTICLE_PREMULTIPLIED_ALPHA_BLEND: NonNullable<MaterialRenderState['blend']> = {\n color: { srcFactor: 'one', dstFactor: 'one-minus-src-alpha', operation: 'add' },\n alpha: { srcFactor: 'one', dstFactor: 'one-minus-src-alpha', operation: 'add' },\n};\n\nconst PARTICLE_ADDITIVE_BLEND: NonNullable<MaterialRenderState['blend']> = {\n color: { srcFactor: 'one', dstFactor: 'one', operation: 'add' },\n alpha: { srcFactor: 'one', dstFactor: 'one-minus-src-alpha', operation: 'add' },\n};\n\n/**\n * Resolve the one material pass that is meaningful for a particle projection.\n * A regular Forward pass is intentionally ignored: VFX vertex layouts are a\n * different contract, so silently accepting it would compile the wrong input\n * shape and make authored particle shaders appear to work while never running.\n */\nexport function particleMaterialPass(\n kind: ParticleRendererKind,\n material: MaterialAsset | undefined,\n): ParticleMaterialPass {\n const pass = material?.passes?.find((candidate) => candidate.name === `particle-${kind}`);\n return {\n shader: pass?.program.module ?? PARTICLE_SHADER_IDENTIFIERS[kind],\n ...(pass?.renderState === undefined\n ? {}\n : { renderState: pass.renderState as MaterialRenderState }),\n };\n}\n\n/**\n * Resolve the default pipeline state for a particle renderer.\n *\n * The built-in particle shaders emit premultiplied RGB (`rgb * alpha`). The\n * renderer's explicit blend mode therefore has to become a matching fixed\n * function state; leaving the state undefined makes transparent billboard\n * corners overwrite the scene with their zero RGB (the visible black-box\n * failure). An authored particle pass remains authoritative and bypasses\n * these defaults.\n */\nexport function particleRendererRenderState(\n kind: ParticleRendererKind,\n blend: ParticleBlendMode,\n authored: MaterialRenderState | undefined,\n): MaterialRenderState | undefined {\n if (authored !== undefined) return authored;\n const isTopology = kind === 'ribbon' || kind === 'trail' || kind === 'beam';\n if (kind !== 'billboard' && !isTopology) return undefined;\n const mode = kind === 'billboard' ? (blend ?? 'alpha') : 'alpha';\n if (mode === 'opaque-cutout') {\n return {\n cullMode: 'none',\n depthCompare: 'less-equal',\n depthWriteEnabled: true,\n };\n }\n return {\n cullMode: 'none',\n depthCompare: 'less-equal',\n depthWriteEnabled: false,\n blend: mode === 'additive' ? PARTICLE_ADDITIVE_BLEND : PARTICLE_PREMULTIPLIED_ALPHA_BLEND,\n };\n}\n\n/** True when the authored particle shader consumes the standard material bind group. */\nexport function particleMaterialUsesBindings(material: MaterialAsset | undefined): boolean {\n return (material?.parameters?.length ?? 0) > 0;\n}\n\n/**\n * Return the scene-depth binding slot required by a particle material shader.\n *\n * Custom particle shaders historically bind only the sampled depth resource at\n * group(0)/binding(0), while the renderer-owned billboard shader also consumes\n * the view UBO at binding(0) and therefore uses depth at binding(1). Keep this\n * choice derived from the renderer contract instead of assuming every\n * billboard has the built-in layout.\n */\nexport function particleMaterialSceneDepthBinding(\n contract: RenderFeatureMaterialShaderBindingContract | undefined,\n): 0 | 1 | undefined {\n if (contract === 'group-0-resource') return 0;\n if (contract === 'view-and-scene-depth') return 1;\n return undefined;\n}\n\nfunction floatAttribute(value: ArrayBuffer | Float32Array | Uint16Array | undefined): Float32Array {\n if (value instanceof Float32Array) return value;\n if (value instanceof Uint16Array) return Float32Array.from(value);\n return value === undefined ? new Float32Array() : new Float32Array(value);\n}\n\nexport function canonicalMeshVertices(mesh: MeshAsset): Float32Array {\n if (mesh.vertices.length > 0 && mesh.vertices.length % 12 === 0) return mesh.vertices;\n const positions = floatAttribute(mesh.attributes.position);\n const vertexCount = Math.floor(positions.length / 3);\n const normals = floatAttribute(mesh.attributes.normal);\n const uvs = floatAttribute(mesh.attributes.uv);\n const tangents = floatAttribute(mesh.attributes.tangent);\n const result = new Float32Array(vertexCount * 12);\n for (let index = 0; index < vertexCount; index += 1) {\n const target = index * 12;\n result.set(positions.subarray(index * 3, index * 3 + 3), target);\n result.set(\n normals.length >= index * 3 + 3 ? normals.subarray(index * 3, index * 3 + 3) : [0, 0, 1],\n target + 3,\n );\n result.set(\n uvs.length >= index * 2 + 2 ? uvs.subarray(index * 2, index * 2 + 2) : [0, 0],\n target + 6,\n );\n result.set(\n tangents.length >= index * 4 + 4 ? tangents.subarray(index * 4, index * 4 + 4) : [1, 0, 0, 1],\n target + 8,\n );\n }\n return result;\n}\n","import type { VfxGpuStageReflection } from '@forgeax/engine-vfx';\nimport type {\n RenderFeatureGpuBindingsRef,\n RenderFeatureGpuDispatch,\n} from '../../../render/src/features/prepared-gpu-work.js';\n\nconst MANAGED_STAGES = new Set(['spawn', 'update', 'scan', 'compact']);\nconst RESOURCE_NAMES = new Set([\n 'particles',\n 'runtime',\n 'aliveIndices',\n 'counters',\n 'indirect',\n 'scratch',\n 'billboardInstances',\n 'channelInputs',\n 'events',\n 'eventCounters',\n]);\nconst STAGE_ID = /^[a-z][a-z0-9-]{0,31}$/;\nconst ENTRY_POINT = /^forgeax_vfx_stage_[a-z][a-z0-9-]{0,31}_main$/;\nconst MAX_ITERATIONS = 64;\n\nexport interface VfxValidatedStage {\n readonly id: string;\n readonly entry: string;\n readonly entryPoint: string;\n readonly domain: 'particle';\n readonly resources: readonly {\n readonly name: string;\n readonly access: VfxGpuStageReflection['resources'][number]['access'];\n }[];\n readonly dependsOn: readonly string[];\n readonly iterationBudget: number;\n}\n\nexport interface VfxStageReadiness {\n readonly id: string;\n readonly state: 'ready' | 'candidate-rejected' | 'stale' | 'rebuilding';\n readonly generation: number;\n readonly lastKnownGoodGeneration?: number;\n readonly retryable: boolean;\n readonly error?: string;\n}\n\nexport interface VfxStagePlanObservation {\n readonly validatedStagePlan: VfxValidatedStagePlan;\n readonly stageReadiness: readonly VfxStageReadiness[];\n readonly stageOutput: 'active' | 'last-known-good' | 'empty';\n readonly lastKnownGoodStage:\n | { readonly fingerprint: string; readonly generation: number }\n | undefined;\n}\n\nexport interface VfxValidatedStagePlan {\n readonly stages: readonly VfxValidatedStage[];\n readonly fingerprint: string;\n readonly generation: number;\n}\n\nexport interface VfxStagePlanError {\n readonly code:\n | 'stage-id-invalid'\n | 'stage-entry-point-invalid'\n | 'stage-domain-invalid'\n | 'stage-resource-invalid'\n | 'stage-dependency-invalid'\n | 'stage-cycle'\n | 'stage-budget-invalid';\n readonly stageId: string;\n readonly hint: string;\n}\n\nexport type VfxStageRecovery = 'device-loss' | 'stale';\n\nfunction failure(\n code: VfxStagePlanError['code'],\n stageId: string,\n hint: string,\n): { ok: false; error: VfxStagePlanError } {\n return { ok: false, error: { code, stageId, hint } };\n}\n\nfunction stableStage(stage: VfxGpuStageReflection): VfxValidatedStage {\n return {\n id: stage.id,\n entry: stage.entry,\n entryPoint: stage.entryPoint,\n domain: stage.domain,\n resources: Object.freeze(\n stage.resources.map((resource) => ({ name: resource.name, access: resource.access })),\n ),\n dependsOn: Object.freeze([...stage.dependsOn]),\n iterationBudget: stage.iterationBudget,\n };\n}\n\n/** Validate the compiler reflection before a RenderFeature can contribute it. */\nexport function validatedStagePlan(\n reflection: VfxGpuStageReflection[] | readonly VfxGpuStageReflection[] | undefined,\n generation: number,\n):\n | { readonly ok: true; readonly value: VfxValidatedStagePlan }\n | { readonly ok: false; readonly error: VfxStagePlanError } {\n const source = reflection ?? [];\n const ids = new Set<string>();\n const stages: VfxValidatedStage[] = [];\n for (const stage of source) {\n if (!STAGE_ID.test(stage.id) || ids.has(stage.id)) {\n return failure(\n 'stage-id-invalid',\n stage.id,\n 'recook the effect with unique bounded stage ids',\n );\n }\n ids.add(stage.id);\n if (stage.domain !== 'particle' || MANAGED_STAGES.has(stage.domain)) {\n return failure('stage-domain-invalid', stage.id, 'use the managed particle dispatch domain');\n }\n if (!ENTRY_POINT.test(stage.entryPoint)) {\n return failure(\n 'stage-entry-point-invalid',\n stage.id,\n 'use the compiler-generated stage entry point',\n );\n }\n if (\n !Number.isInteger(stage.iterationBudget) ||\n stage.iterationBudget < 1 ||\n stage.iterationBudget > MAX_ITERATIONS\n ) {\n return failure(\n 'stage-budget-invalid',\n stage.id,\n 'use an integer iteration budget from 1 through 64',\n );\n }\n const resources = new Set<string>();\n for (const resource of stage.resources) {\n if (\n !RESOURCE_NAMES.has(resource.name) ||\n !['read', 'write', 'read-write'].includes(resource.access)\n ) {\n return failure(\n 'stage-resource-invalid',\n stage.id,\n 'declare only managed VFX resources with a supported access mode',\n );\n }\n if (resources.has(resource.name)) {\n return failure(\n 'stage-resource-invalid',\n stage.id,\n 'declare each managed VFX resource once',\n );\n }\n resources.add(resource.name);\n }\n stages.push(stableStage(stage));\n }\n const byId = new Map(stages.map((stage) => [stage.id, stage]));\n const visiting = new Set<string>();\n const visited = new Set<string>();\n const ordered: VfxValidatedStage[] = [];\n const visit = (stage: VfxValidatedStage): VfxStagePlanError | undefined => {\n if (visited.has(stage.id)) return undefined;\n if (visiting.has(stage.id))\n return {\n code: 'stage-cycle',\n stageId: stage.id,\n hint: 'remove the stage dependency cycle and recook the effect',\n };\n visiting.add(stage.id);\n for (const dependency of stage.dependsOn) {\n if (MANAGED_STAGES.has(dependency)) continue;\n const dependencyStage = byId.get(dependency);\n if (dependencyStage === undefined) {\n return {\n code: 'stage-dependency-invalid',\n stageId: stage.id,\n hint: 'declare every stage dependency or use a managed stage',\n };\n }\n const error = visit(dependencyStage);\n if (error !== undefined) return error;\n }\n visiting.delete(stage.id);\n visited.add(stage.id);\n ordered.push(stage);\n return undefined;\n };\n for (const stage of stages) {\n const error = visit(stage);\n if (error !== undefined) return { ok: false, error };\n }\n const normalized = Object.freeze(ordered);\n return {\n ok: true,\n value: Object.freeze({\n stages: normalized,\n fingerprint: JSON.stringify(normalized),\n generation,\n }),\n };\n}\n\nexport function stageDispatches(\n plan: VfxValidatedStagePlan,\n workgroups: number,\n bindings: RenderFeatureGpuBindingsRef,\n): readonly RenderFeatureGpuDispatch[] {\n return plan.stages.map((stage) => ({\n entryPoint: stage.entryPoint,\n workgroups: [workgroups] as const,\n bindings,\n }));\n}\n\nexport function observeStagePlan(\n candidate: ReturnType<typeof validatedStagePlan>,\n generation: number,\n lastKnownGoodStage: VfxValidatedStagePlan | undefined,\n): VfxStagePlanObservation {\n if (candidate.ok) {\n return {\n validatedStagePlan: candidate.value,\n stageReadiness: candidate.value.stages.map((stage) => ({\n id: stage.id,\n state: 'ready' as const,\n generation,\n lastKnownGoodGeneration: generation,\n retryable: false,\n })),\n stageOutput: candidate.value.stages.length === 0 ? 'empty' : 'active',\n lastKnownGoodStage:\n candidate.value.stages.length === 0\n ? lastKnownGoodStage === undefined\n ? undefined\n : {\n fingerprint: lastKnownGoodStage.fingerprint,\n generation: lastKnownGoodStage.generation,\n }\n : { fingerprint: candidate.value.fingerprint, generation },\n };\n }\n const retained = lastKnownGoodStage ?? { stages: [], fingerprint: '', generation };\n return {\n validatedStagePlan: retained,\n stageReadiness: [\n {\n id: candidate.error.stageId,\n state: 'candidate-rejected',\n generation,\n ...(lastKnownGoodStage === undefined\n ? {}\n : { lastKnownGoodGeneration: lastKnownGoodStage.generation }),\n retryable: true,\n error: candidate.error.code,\n },\n ],\n stageOutput: lastKnownGoodStage === undefined ? 'empty' : 'last-known-good',\n lastKnownGoodStage:\n lastKnownGoodStage === undefined\n ? undefined\n : {\n fingerprint: lastKnownGoodStage.fingerprint,\n generation: lastKnownGoodStage.generation,\n },\n };\n}\n\nexport function stageRecoveryReadiness(\n plan: VfxValidatedStagePlan,\n generation: number,\n recovery: VfxStageRecovery,\n): readonly VfxStageReadiness[] {\n return plan.stages.map((stage) => ({\n id: stage.id,\n state: recovery === 'stale' ? ('stale' as const) : ('rebuilding' as const),\n generation,\n lastKnownGoodGeneration: plan.generation,\n retryable: true,\n error: recovery,\n }));\n}\n","import type { EntityHandle, World } from '@forgeax/engine-ecs';\nimport { frustum } from '@forgeax/engine-math';\nimport type { RenderFeature, RenderFeaturePlan } from '@forgeax/engine-render';\nimport { GlobalTransform } from '@forgeax/engine-scene';\nimport { err, type MaterialAsset, type MeshAsset, ok } from '@forgeax/engine-types';\nimport type { ParticleRendererSource } from '@forgeax/engine-vfx';\nimport {\n VFX_GPU_RUNTIME_RESOURCE_KEY,\n type VfxGpuRuntime,\n type VfxGpuTickIntent,\n} from '@forgeax/engine-vfx';\nimport { RenderFeatureStageFailedError } from '../../../render/src/errors/render';\nimport { RENDER_FEATURE_VERTEX_LAYOUTS } from '../../../render/src/features/prepared-graphics';\nimport type { VfxDataInterfaceRegistry } from '../host/data-interface-providers.js';\nimport type { ParticleRenderCamera } from './camera.js';\nimport {\n encodeEventInputs,\n eventCapacity,\n eventInputCapacity,\n VFX_EVENT_BYTES,\n VFX_EVENT_INPUT_BYTES,\n} from './event-resources.js';\nimport {\n canonicalMeshVertices,\n createTopologyResourcePlan,\n PARTICLE_SHADER_IDENTIFIERS,\n particleMaterialPass,\n particleMaterialSceneDepthBinding,\n particleMaterialUsesBindings,\n particleRendererRenderState,\n} from './particle-resources.js';\nimport type { VfxStagePlanObservation, VfxValidatedStagePlan } from './stage-plan.js';\nimport { validatedStagePlan } from './stage-plan.js';\n\nconst IDENTITY = 'forgeax.vfx-render.gpu-particles';\nconst WORKGROUP_SIZE = 256;\nconst PARTICLE_BYTES = 80;\nconst BILLBOARD_INSTANCE_BYTES = 31 * 4;\nconst MESH_INSTANCE_BYTES = 28 * 4;\nconst COUNTERS_BYTES = 24;\nconst RUNTIME_BYTES = 72 * 4;\nconst IDENTITY_MATRIX = new Float32Array([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]);\n\ntype ParticleRendererKind = ParticleRendererSource['kind'];\ntype ParticleTopologyRenderer = Extract<ParticleRendererSource, { readonly capacity: number }>;\ntype ParticleTopologyKind = ParticleTopologyRenderer['kind'];\ntype VfxStageOutput = VfxStagePlanObservation['stageOutput'];\n\ninterface VfxRenderStageState {\n readonly stageOutput: VfxStageOutput;\n}\n\ninterface VfxRenderInspectSnapshot extends VfxRenderStageState {\n readonly topology: ParticleRendererKind;\n readonly counters: {\n readonly capacity: number;\n readonly produced: number;\n readonly dropped: number;\n };\n readonly stageReadiness: readonly unknown[];\n readonly providerReadiness: unknown;\n readonly gpuTiming: unknown;\n}\n\nexport interface VfxRenderInspectInput {\n readonly topology: ParticleRendererKind;\n readonly capacity: number;\n readonly produced: number;\n readonly dropped: number;\n readonly stageReadiness: readonly unknown[];\n readonly stageOutput?: VfxStageOutput;\n readonly providerReadiness: unknown;\n readonly gpuTiming: unknown;\n}\n\nexport function createVfxRenderInspectSnapshot(\n input: VfxRenderInspectInput,\n): VfxRenderInspectSnapshot {\n return {\n topology: input.topology,\n counters: { capacity: input.capacity, produced: input.produced, dropped: input.dropped },\n stageReadiness: input.stageReadiness,\n stageOutput: input.stageOutput ?? 'empty',\n providerReadiness: input.providerReadiness,\n gpuTiming: input.gpuTiming,\n } as const;\n}\n\nexport interface BillboardAdvancedSample {\n readonly age: number;\n readonly lifetime: number;\n readonly particleDepth: number;\n readonly sceneDepth: number;\n readonly depthAvailable: boolean;\n}\n\nexport function resolveBillboardAdvancedState(\n renderer: Extract<ParticleRendererSource, { readonly kind: 'billboard' }>,\n sample: BillboardAdvancedSample,\n) {\n if (renderer.softParticle !== undefined && !sample.depthAvailable) {\n return err({\n code: 'vfx-renderer-depth-missing' as const,\n expected: 'a scene-depth provider for soft particles',\n hint: 'attach the scene-depth data interface or disable soft particles',\n detail: { path: 'renderer.softParticle' },\n });\n }\n const sheet = renderer.textureSheet;\n const frameCount = sheet?.frameCount ?? (sheet === undefined ? 1 : sheet.columns * sheet.rows);\n const frameIndex =\n sheet === undefined || sheet.frameRate === 0\n ? 0\n : Math.min(\n frameCount - 1,\n Math.max(0, Math.floor(Math.max(0, sample.age) * sheet.frameRate)),\n );\n const softParticleFade =\n renderer.softParticle === undefined\n ? 1\n : Math.max(\n 0,\n Math.min(\n 1,\n (sample.sceneDepth - sample.particleDepth) / renderer.softParticle.fadeDistance,\n ),\n );\n return ok({\n frameIndex,\n pivot: renderer.pivot ?? ([0, 0] as const),\n softParticleFade,\n sortingKey: renderer.sorting === 'back-to-front' ? sample.particleDepth : 0,\n });\n}\n\nexport function topologyRecoveryHint(\n topology: ParticleTopologyKind,\n reason: 'capacity' | 'broken' | 'degenerate' | 'device',\n): string {\n if (reason === 'capacity')\n return `${topology} capacity overflow was bounded; increase its explicit capacity`;\n if (reason === 'broken')\n return `${topology} continuity broke; inspect its explicit source key and keep the last valid segment`;\n if (reason === 'degenerate')\n return `${topology} produced no drawable segment; preserve zero output and inspect source endpoints`;\n return `${topology} device resources recovered from the last known good generation`;\n}\n\ninterface GpuParticleFeatureOptions {\n readonly camera: { read(world: World): ParticleRenderCamera | undefined };\n readonly dataInterfaces?: Pick<VfxDataInterfaceRegistry, 'resolve'>;\n readonly material?: { read(world: World, guid: string): MaterialAsset | undefined };\n readonly mesh?: { read(world: World, guid: string): MeshAsset | undefined };\n readonly playerConsumption?: {\n readonly isEnabled: (world: World, player: EntityHandle) => boolean;\n };\n}\n\ninterface ExtractedWorld {\n readonly world: World;\n readonly runtime: VfxGpuRuntime;\n readonly camera: ParticleRenderCamera;\n readonly intents: readonly VfxGpuTickIntent[];\n}\n\ninterface ExtractedFrame {\n readonly worlds: readonly ExtractedWorld[];\n readonly frameNumber: number;\n}\n\nfunction finite(value: unknown, fallback: number): number {\n return typeof value === 'number' && Number.isFinite(value) ? value : fallback;\n}\n\nfunction vector(value: unknown, fallback: readonly number[], size: number): readonly number[] {\n return Array.isArray(value)\n ? Array.from({ length: size }, (_, index) => finite(value[index], fallback[index] ?? 0))\n : fallback;\n}\n\nfunction runtimeData(\n intent: VfxGpuTickIntent,\n camera: ParticleRenderCamera,\n material: MaterialAsset | undefined,\n localToWorld: Float32Array,\n renderer?: ParticleRendererSource,\n rendererIndex = 0,\n): Uint8Array {\n const storage = new ArrayBuffer(RUNTIME_BYTES);\n const floats = new Float32Array(storage);\n const words = new Uint32Array(storage);\n floats[0] = intent.fixedDelta;\n words[1] = intent.phaseTick;\n words[2] = intent.seed;\n words[3] = intent.playCycle;\n words[4] = intent.emitter.capacity;\n words[5] = intent.spawnCount;\n words[6] = intent.firstParticleId;\n words[7] = intent.emitter.renderers.length;\n floats.set(camera.viewProjection, 8);\n floats.set(camera.right, 24);\n floats.set(camera.up, 28);\n const values = material?.values ?? {};\n floats.set(vector(values.baseColor, [1, 1, 1, 1], 4), 32);\n const emissive = vector(values.emissive, [0, 0, 0], 3);\n floats.set(emissive, 36);\n floats[39] = finite(values.emissiveIntensity, 0);\n floats[40] = finite(values.metallic, 0);\n floats[41] = finite(values.roughness, 0.5);\n floats[42] = finite(values.clearcoat, 0);\n floats[43] = finite(values.clearcoatRoughness, 0.5);\n floats.set(localToWorld, 44);\n words[60] = rendererIndex;\n words[61] = renderer?.kind === 'trail' ? renderer.historyLength : 0;\n words[62] =\n renderer?.kind === 'ribbon' || renderer?.kind === 'trail' || renderer?.kind === 'beam'\n ? renderer.capacity\n : intent.emitter.capacity;\n words[63] =\n renderer?.kind === 'billboard' && renderer.sorting === 'back-to-front'\n ? 2\n : renderer?.kind === 'billboard' && renderer.sorting === 'emitter'\n ? 1\n : 0;\n floats[64] =\n renderer?.kind === 'billboard'\n ? (renderer.pivot?.[0] ?? 0)\n : renderer?.kind === 'ribbon' || renderer?.kind === 'trail' || renderer?.kind === 'beam'\n ? (renderer.width ?? 0.1)\n : 0.1;\n floats[65] = renderer?.kind === 'billboard' ? (renderer.pivot?.[1] ?? 0) : 0;\n floats[66] = renderer?.kind === 'billboard' ? (renderer.softParticle?.fadeDistance ?? 0) : 0;\n const sheet = renderer?.kind === 'billboard' ? renderer.textureSheet : undefined;\n floats[68] = sheet?.columns ?? 1;\n floats[69] = sheet?.rows ?? 1;\n floats[70] = sheet?.frameRate ?? 0;\n floats[71] = sheet?.frameCount ?? (sheet === undefined ? 1 : sheet.columns * sheet.rows);\n return new Uint8Array(storage);\n}\n\nfunction emitterTransform(world: World, intent: VfxGpuTickIntent): Float32Array {\n if (intent.emitter.space === 'world') return IDENTITY_MATRIX;\n const transform = world.get(intent.player, GlobalTransform);\n return transform.ok ? transform.value.world : IDENTITY_MATRIX;\n}\n\nfunction emitterVisible(\n intent: VfxGpuTickIntent,\n camera: ParticleRenderCamera,\n localToWorld: Float32Array,\n): boolean {\n const bounds = intent.emitter.bounds;\n const center =\n bounds.kind === 'sphere'\n ? bounds.center\n : ([\n (bounds.min[0] + bounds.max[0]) * 0.5,\n (bounds.min[1] + bounds.max[1]) * 0.5,\n (bounds.min[2] + bounds.max[2]) * 0.5,\n ] as const);\n const radius =\n bounds.kind === 'sphere'\n ? bounds.radius\n : Math.hypot(\n (bounds.max[0] - bounds.min[0]) * 0.5,\n (bounds.max[1] - bounds.min[1]) * 0.5,\n (bounds.max[2] - bounds.min[2]) * 0.5,\n );\n const matrix = (index: number): number => localToWorld[index] ?? 0;\n const worldCenter = new Float32Array([\n matrix(0) * center[0] + matrix(4) * center[1] + matrix(8) * center[2] + matrix(12),\n matrix(1) * center[0] + matrix(5) * center[1] + matrix(9) * center[2] + matrix(13),\n matrix(2) * center[0] + matrix(6) * center[1] + matrix(10) * center[2] + matrix(14),\n ]);\n const scale = Math.max(\n Math.hypot(matrix(0), matrix(1), matrix(2)),\n Math.hypot(matrix(4), matrix(5), matrix(6)),\n Math.hypot(matrix(8), matrix(9), matrix(10)),\n );\n const planes = frustum.fromViewProjection(frustum.create(), camera.viewProjection);\n return frustum.intersectsSphere(planes, worldCenter, radius * scale);\n}\n\nfunction resetData(size: number): Uint8Array {\n return new Uint8Array(size);\n}\n\nfunction requiresSceneDepth(intent: VfxGpuTickIntent): boolean {\n return (intent.emitter.reflection.dataInterfaces ?? []).some(\n (requirement) => requirement.kind === 'scene-depth',\n );\n}\n\nfunction planFailure(): RenderFeatureStageFailedError {\n return new RenderFeatureStageFailedError(IDENTITY, -1, 'plan', 'next-frame');\n}\n\ntype PlanResource = RenderFeaturePlan['resources'][number];\ntype PlanPass = RenderFeaturePlan['passes'][number];\n\nfunction planName(value: string, maxLength = 24): string {\n const normalized = value.toLowerCase().replaceAll(/[^a-z0-9.-]/g, '-');\n return (normalized.length === 0 ? 'unnamed' : normalized).slice(0, maxLength);\n}\n\nfunction computeBindingEntries(\n intent: VfxGpuTickIntent,\n resources: Readonly<Record<number, string>>,\n): readonly { readonly binding: number; readonly resource: string }[] {\n const declared = new Set(\n (intent.emitter.reflection.bindings[0]?.entries ?? [])\n .filter((entry) => entry.buffer !== undefined)\n .map((entry) => entry.binding),\n );\n return Object.entries(resources).flatMap(([binding, resource]) =>\n declared.has(Number(binding)) ? [{ binding: Number(binding), resource }] : [],\n );\n}\n\nfunction simulationDispatches(\n intent: VfxGpuTickIntent,\n stages: VfxValidatedStagePlan,\n): Extract<PlanPass, { readonly kind: 'compute' }>['dispatches'] {\n const groups = Math.max(1, Math.ceil(intent.emitter.capacity / WORKGROUP_SIZE));\n return [\n { kind: 'direct', entryPoint: 'forgeax_vfx_spawn_main', workgroups: [groups] },\n { kind: 'direct', entryPoint: 'forgeax_vfx_update_main', workgroups: [groups] },\n ...stages.stages.map((stage) => ({\n kind: 'direct' as const,\n entryPoint: stage.entryPoint,\n workgroups: [groups] as const,\n })),\n { kind: 'direct', entryPoint: 'forgeax_vfx_scan_blocks_main', workgroups: [groups] },\n { kind: 'direct', entryPoint: 'forgeax_vfx_scan_block_offsets_main', workgroups: [1] },\n { kind: 'direct', entryPoint: 'forgeax_vfx_add_offsets_main', workgroups: [groups] },\n { kind: 'direct', entryPoint: 'forgeax_vfx_compact_main', workgroups: [groups] },\n {\n kind: 'direct',\n entryPoint: 'forgeax_vfx_event_main',\n workgroups: [Math.max(1, Math.ceil(eventInputCapacity(intent.emitter) / 64))],\n },\n ];\n}\n\nexport function gpuParticleRenderFeature(\n options: GpuParticleFeatureOptions,\n): RenderFeature<ExtractedFrame> {\n return {\n identity: IDENTITY,\n requiredCapabilities: ['compute', 'indirectDrawing'],\n // Generated emitter programs are first-use assets. They must hand a\n // WebGPU module to the prepared feature pipeline without waiting for the\n // diagnostic-only getCompilationInfo() round trip; pipeline creation still\n // validates the module before the pass is submitted.\n shaderModuleMode: 'immediate',\n requiredMaterialShaders: Object.values(PARTICLE_SHADER_IDENTIFIERS),\n extract: (context) => {\n const extracted: ExtractedWorld[] = [];\n for (const world of context.worlds) {\n if (!world.hasResource(VFX_GPU_RUNTIME_RESOURCE_KEY)) continue;\n const camera = options.camera.read(world);\n if (camera === undefined) continue;\n const runtime = world.getResource<VfxGpuRuntime>(VFX_GPU_RUNTIME_RESOURCE_KEY);\n const intents = runtime.snapshot().filter((intent) => {\n if (options.playerConsumption?.isEnabled(world, intent.player) === false) return false;\n const requirements = intent.emitter.reflection.dataInterfaces ?? [];\n return (\n requirements.length === 0 ||\n options.dataInterfaces?.resolve(requirements, intent.instanceGeneration).ok === true\n );\n });\n extracted.push({ world, runtime, camera, intents });\n }\n return ok({ worlds: extracted, frameNumber: context.frameNumber });\n },\n plan: (frame, context) => {\n const resources: PlanResource[] = [];\n const passes: PlanPass[] = [];\n const dispatchedIntents = new Set<VfxGpuTickIntent>();\n const colorTarget =\n context.targets.find((candidate) => candidate.kind === 'color') ??\n context.targets.find((candidate) => candidate.kind === 'swapchain');\n const depthTarget = context.targets.find((candidate) => candidate.kind === 'depth');\n\n for (const [worldIndex, entry] of frame.worlds.entries()) {\n for (const [intentIndex, intent] of entry.intents.entries()) {\n if (!entry.runtime.isEmitterSessionEnabled(intent.player, intent.emitter.id)) continue;\n const localToWorld = emitterTransform(entry.world, intent);\n const visible = emitterVisible(intent, entry.camera, localToWorld);\n entry.runtime.setEmitterCameraVisibility(intent.player, intent.emitter.id, visible);\n if (!visible) continue;\n if (requiresSceneDepth(intent) && depthTarget === undefined) continue;\n\n const stagePlan = validatedStagePlan(\n intent.emitter.reflection.stages,\n intent.instanceGeneration,\n );\n if (!stagePlan.ok) return err(planFailure());\n\n const prefix = `vfx.w-${worldIndex}.i-${intentIndex}.${planName(intent.emitter.id)}`;\n const program = `${prefix}.compute-program`;\n const particles = `${prefix}.particles`;\n const runtime = `${prefix}.runtime`;\n const aliveIndices = `${prefix}.alive-indices`;\n const counters = `${prefix}.counters`;\n const indirect = `${prefix}.indirect`;\n const scratch = `${prefix}.scratch`;\n const sharedInstances = `${prefix}.shared-instances`;\n const eventInputs = `${prefix}.event-inputs`;\n const events = `${prefix}.events`;\n const bindings = `${prefix}.simulation-bindings`;\n const capacity = intent.emitter.capacity;\n const renderers = intent.emitter.renderers;\n const meshes = renderers.map((renderer) =>\n renderer.kind === 'mesh' ? options.mesh?.read(entry.world, renderer.mesh) : undefined,\n );\n const indirectWords = new Uint32Array(Math.max(1, renderers.length) * 5);\n\n for (const [rendererIndex, renderer] of renderers.entries()) {\n const mesh = meshes[rendererIndex];\n const submesh =\n renderer.kind === 'mesh' ? mesh?.submeshes[renderer.submesh ?? 0] : undefined;\n if (renderer.kind === 'mesh' && submesh === undefined) return err(planFailure());\n if (\n (renderer.kind === 'ribbon' ||\n renderer.kind === 'trail' ||\n renderer.kind === 'beam') &&\n !createTopologyResourcePlan(renderer).ok\n ) {\n return err(planFailure());\n }\n indirectWords[rendererIndex * 5] =\n renderer.kind === 'mesh'\n ? mesh?.indices === undefined\n ? (submesh?.vertexCount ?? 0)\n : (submesh?.indexCount ?? 0)\n : 6;\n indirectWords[rendererIndex * 5 + 2] =\n renderer.kind === 'mesh' && mesh?.indices !== undefined\n ? (submesh?.indexOffset ?? 0)\n : 0;\n }\n\n const scratchBytes = (capacity * 2 + Math.ceil(capacity / WORKGROUP_SIZE)) * 4;\n const eventInputBytes = Math.max(\n 4,\n eventInputCapacity(intent.emitter) * VFX_EVENT_INPUT_BYTES,\n );\n const eventBytes = Math.max(4, eventCapacity(intent.emitter) * VFX_EVENT_BYTES);\n resources.push(\n {\n kind: 'compute-program',\n name: program,\n program: {\n wgsl: intent.emitter.wgsl,\n entryPoints: intent.emitter.reflection.entryPoints,\n bindings: intent.emitter.reflection.bindings,\n },\n },\n {\n kind: 'buffer',\n name: particles,\n size: capacity * PARTICLE_BYTES,\n usage: ['storage'],\n ...(intent.reset ? { data: resetData(capacity * PARTICLE_BYTES) } : {}),\n },\n { kind: 'buffer', name: aliveIndices, size: capacity * 4, usage: ['storage'] },\n {\n kind: 'buffer',\n name: counters,\n size: COUNTERS_BYTES,\n usage: ['storage'],\n ...(intent.reset ? { data: resetData(COUNTERS_BYTES) } : {}),\n },\n {\n kind: 'buffer',\n name: indirect,\n size: indirectWords.byteLength,\n usage: ['storage', 'indirect'],\n data: indirectWords,\n },\n {\n kind: 'buffer',\n name: scratch,\n size: scratchBytes,\n usage: ['storage'],\n ...(intent.reset ? { data: resetData(scratchBytes) } : {}),\n },\n {\n kind: 'buffer',\n name: sharedInstances,\n size: capacity * Math.max(BILLBOARD_INSTANCE_BYTES, MESH_INSTANCE_BYTES),\n usage: ['storage', 'vertex'],\n },\n {\n kind: 'buffer',\n name: eventInputs,\n size: eventInputBytes,\n usage: ['storage'],\n data: encodeEventInputs(intent),\n },\n {\n kind: 'buffer',\n name: events,\n size: eventBytes,\n usage: ['storage'],\n ...(intent.reset ? { data: resetData(eventBytes) } : {}),\n },\n {\n kind: 'buffer',\n name: runtime,\n size: RUNTIME_BYTES,\n usage: ['uniform'],\n data: runtimeData(intent, entry.camera, undefined, localToWorld),\n },\n {\n kind: 'compute-bindings',\n name: bindings,\n program,\n entries: computeBindingEntries(intent, {\n 0: particles,\n 1: runtime,\n 2: aliveIndices,\n 3: counters,\n 4: indirect,\n 5: scratch,\n 6: sharedInstances,\n 8: eventInputs,\n 9: events,\n }),\n },\n );\n\n const entryPoints = new Set(intent.emitter.reflection.entryPoints);\n const dispatches = simulationDispatches(intent, stagePlan.value).filter((dispatch) =>\n entryPoints.has(dispatch.entryPoint),\n );\n if (dispatches.length > 0) {\n passes.push({\n kind: 'compute',\n name: `${prefix}.simulate`,\n program,\n bindings,\n dispatches,\n });\n dispatchedIntents.add(intent);\n }\n\n for (const [rendererIndex, renderer] of renderers.entries()) {\n const rendererPrefix = `${prefix}.renderer-${rendererIndex}`;\n const isBillboard = renderer.kind === 'billboard';\n const isTopology =\n renderer.kind === 'ribbon' || renderer.kind === 'trail' || renderer.kind === 'beam';\n const topologyPlan = isTopology ? createTopologyResourcePlan(renderer) : undefined;\n if (topologyPlan !== undefined && !topologyPlan.ok) return err(planFailure());\n const material = options.material?.read(entry.world, renderer.material);\n const materialPass = particleMaterialPass(renderer.kind, material);\n const mesh = meshes[rendererIndex];\n const submesh =\n renderer.kind === 'mesh' ? mesh?.submeshes[renderer.submesh ?? 0] : undefined;\n const indexFormat = mesh?.indices instanceof Uint32Array ? 'uint32' : 'uint16';\n const sceneDepthBinding = isBillboard\n ? particleMaterialSceneDepthBinding(\n context.materialShaderBindingContract?.(materialPass.shader) ??\n (materialPass.shader === PARTICLE_SHADER_IDENTIFIERS.billboard\n ? 'view-and-scene-depth'\n : undefined),\n )\n : undefined;\n const instances = `${rendererPrefix}.instances`;\n const history = `${rendererPrefix}.history`;\n const projectionRuntime = `${rendererPrefix}.runtime`;\n const projectionBindings = `${rendererPrefix}.compute-bindings`;\n const vertexLayout = isBillboard\n ? RENDER_FEATURE_VERTEX_LAYOUTS.billboardMaterialInstance\n : isTopology\n ? RENDER_FEATURE_VERTEX_LAYOUTS.topologySegmentInstance\n : RENDER_FEATURE_VERTEX_LAYOUTS.meshGeometryMaterialInstance;\n const instanceBytes = isTopology\n ? (topologyPlan?.value.vertexBytes ?? 16)\n : capacity * (isBillboard ? BILLBOARD_INSTANCE_BYTES : MESH_INSTANCE_BYTES);\n const historyBytes =\n renderer.kind === 'trail'\n ? Math.max(16, renderer.capacity * renderer.historyLength * 16)\n : 16;\n\n resources.push(\n {\n kind: 'buffer',\n name: instances,\n size: instanceBytes,\n usage: ['storage', 'vertex'],\n },\n {\n kind: 'buffer',\n name: history,\n size: historyBytes,\n usage: ['storage'],\n ...(intent.reset ? { data: resetData(historyBytes) } : {}),\n },\n {\n kind: 'buffer',\n name: projectionRuntime,\n size: RUNTIME_BYTES,\n usage: ['uniform'],\n data: runtimeData(\n { ...intent, fixedDelta: 0, spawnCount: 0 },\n entry.camera,\n material,\n localToWorld,\n renderer,\n rendererIndex,\n ),\n },\n {\n kind: 'compute-bindings',\n name: projectionBindings,\n program,\n entries: computeBindingEntries(intent, {\n 0: particles,\n 1: projectionRuntime,\n 2: aliveIndices,\n 3: counters,\n 4: indirect,\n 5: history,\n 6: instances,\n 8: eventInputs,\n 9: events,\n }),\n },\n );\n\n const projectionDispatches: Extract<\n PlanPass,\n { readonly kind: 'compute' }\n >['dispatches'][number][] = [];\n const pushProjection = (entryPoint: string, workgroups: number): void => {\n if (!entryPoints.has(entryPoint)) return;\n projectionDispatches.push({\n kind: 'direct',\n entryPoint,\n workgroups: [Math.max(1, workgroups)],\n });\n };\n if (isBillboard && renderer.sorting === 'back-to-front') {\n pushProjection('forgeax_vfx_sort_main', 1);\n }\n if (renderer.kind === 'trail') {\n pushProjection(\n 'forgeax_vfx_trail_history_main',\n Math.ceil(renderer.capacity / WORKGROUP_SIZE),\n );\n }\n const projectionCount =\n renderer.kind === 'trail'\n ? renderer.capacity * Math.max(1, renderer.historyLength - 1)\n : isTopology\n ? renderer.capacity\n : capacity;\n pushProjection(\n renderer.kind === 'billboard'\n ? 'forgeax_vfx_billboard_main'\n : renderer.kind === 'mesh'\n ? 'forgeax_vfx_mesh_main'\n : `forgeax_vfx_${renderer.kind}_main`,\n Math.ceil(projectionCount / WORKGROUP_SIZE),\n );\n if (projectionDispatches.length > 0) {\n passes.push({\n kind: 'compute',\n name: `${rendererPrefix}.project`,\n program,\n bindings: projectionBindings,\n dispatches: projectionDispatches,\n });\n }\n\n const graphicsProgram = `${rendererPrefix}.graphics-program`;\n const graphicsBindings = `${rendererPrefix}.graphics-bindings`;\n const vertexData = `${rendererPrefix}.vertex-data`;\n const defaultRenderState = particleRendererRenderState(\n renderer.kind,\n renderer.kind === 'billboard' ? renderer.blend : undefined,\n materialPass.renderState,\n );\n const renderState =\n isBillboard && depthTarget !== undefined\n ? { ...(defaultRenderState ?? {}), depthWriteEnabled: false }\n : defaultRenderState;\n resources.push(\n {\n kind: 'graphics-program',\n name: graphicsProgram,\n program: {\n shader: materialPass.shader,\n vertexLayout,\n colorFormats: [colorTarget?.format ?? 'rgba8unorm-srgb'],\n ...(depthTarget === undefined ? {} : { depthFormat: depthTarget.format }),\n sampleCount: colorTarget?.sampleCount ?? 1,\n topology: submesh?.topology ?? 'triangle-list',\n ...(mesh?.indices === undefined ? {} : { indexFormat }),\n ...(renderState === undefined ? {} : { renderState }),\n },\n },\n {\n kind: 'graphics-bindings',\n name: graphicsBindings,\n program: graphicsProgram,\n values: {\n group: 0,\n runtime: projectionRuntime,\n instances,\n ...(sceneDepthBinding === undefined ? {} : { sceneDepthBinding }),\n },\n ...(sceneDepthBinding !== undefined && depthTarget !== undefined\n ? { logicalTargets: { sceneDepth: depthTarget.name } }\n : {}),\n },\n { kind: 'vertex-data', name: vertexData, layout: vertexLayout, buffer: instances },\n );\n const drawBindings = [graphicsBindings];\n if (particleMaterialUsesBindings(material)) {\n const materialBindings = `${rendererPrefix}.material-bindings`;\n resources.push({\n kind: 'graphics-bindings',\n name: materialBindings,\n program: graphicsProgram,\n values: {\n group: 1,\n material: { world: worldIndex, guid: renderer.material },\n },\n });\n drawBindings.push(materialBindings);\n }\n\n const vertexBindings: { readonly slot: number; readonly resource: string }[] = [];\n let indexData:\n | { readonly resource: string; readonly format: 'uint16' | 'uint32' }\n | undefined;\n if (renderer.kind === 'mesh') {\n if (mesh === undefined) return err(planFailure());\n const geometryBuffer = `${rendererPrefix}.geometry-buffer`;\n const geometry = `${rendererPrefix}.geometry`;\n const geometryData = canonicalMeshVertices(mesh);\n resources.push(\n {\n kind: 'buffer',\n name: geometryBuffer,\n size: geometryData.byteLength,\n usage: ['vertex'],\n data: geometryData,\n },\n {\n kind: 'vertex-data',\n name: geometry,\n layout: vertexLayout,\n buffer: geometryBuffer,\n },\n );\n vertexBindings.push(\n { slot: 0, resource: geometry },\n { slot: 1, resource: vertexData },\n );\n if (mesh.indices !== undefined) {\n const indexBuffer = `${rendererPrefix}.index-buffer`;\n const indices = `${rendererPrefix}.indices`;\n resources.push(\n {\n kind: 'buffer',\n name: indexBuffer,\n size: mesh.indices.byteLength,\n usage: ['index'],\n data: mesh.indices,\n },\n {\n kind: 'index-data',\n name: indices,\n format: indexFormat,\n buffer: indexBuffer,\n },\n );\n indexData = { resource: indices, format: indexFormat };\n }\n } else {\n vertexBindings.push({ slot: 0, resource: vertexData });\n }\n\n passes.push({\n kind: 'raster',\n name: `${rendererPrefix}.raster`,\n colorAttachments: [\n {\n target: colorTarget?.name ?? 'swapchain',\n loadOp: 'load',\n storeOp: 'store',\n },\n ],\n ...(depthTarget === undefined\n ? {}\n : {\n depthStencilAttachment: {\n target: depthTarget.name,\n depthLoadOp: 'load',\n depthStoreOp: 'store',\n },\n }),\n ...(sceneDepthBinding !== undefined && depthTarget !== undefined\n ? { sampledTargets: [depthTarget.name] }\n : {}),\n draws: [\n {\n program: graphicsProgram,\n bindings: drawBindings,\n vertexData: vertexBindings,\n ...(indexData === undefined ? {} : { indexData }),\n draw: {\n kind: indexData === undefined ? 'draw-indirect' : 'draw-indexed-indirect',\n resource: indirect,\n offset: rendererIndex * 20,\n },\n },\n ],\n });\n }\n }\n }\n for (const entry of frame.worlds) {\n for (const intent of entry.intents) {\n if (dispatchedIntents.has(intent)) {\n entry.runtime.markEventDispatched(intent.player, intent.eventCounters);\n }\n }\n const lastIntent = entry.intents.at(-1);\n if (lastIntent !== undefined) entry.runtime.commit(lastIntent.sequence);\n }\n return ok<RenderFeaturePlan>({ resources, passes });\n },\n };\n}\n","import { err, ok, type Result } from '@forgeax/engine-types';\nimport {\n resolveVfxDataInterfaces,\n type VfxDataInterfaceError,\n type VfxDataInterfaceKind,\n type VfxDataInterfaceProvider,\n type VfxDataInterfaceRequirement,\n type VfxDataInterfaceResolution,\n type VfxDataInterfaceResource,\n type VfxDataInterfaceToken,\n} from '@forgeax/engine-vfx';\n\nexport type { VfxDataInterfaceProvider } from '@forgeax/engine-vfx';\n\nexport interface VfxDataInterfaceAvailabilitySource {\n readonly available: (generation: number) => boolean;\n}\n\nexport interface VfxDataInterfaceRegistry {\n readonly providers: readonly VfxDataInterfaceProvider[];\n readonly snapshot:\n | {\n readonly generation: number;\n readonly result: Result<VfxDataInterfaceResolution, VfxDataInterfaceError>;\n }\n | undefined;\n register(provider: VfxDataInterfaceProvider): Result<void, VfxDataInterfaceError>;\n resolve(\n requirements: readonly VfxDataInterfaceRequirement[],\n generation: number,\n ): Result<VfxDataInterfaceResolution, VfxDataInterfaceError>;\n}\n\nfunction duplicate(token: VfxDataInterfaceToken, providerId: string): VfxDataInterfaceError {\n return {\n code: 'vfx-data-interface-duplicate',\n expected: 'at most one provider for each reflected Data Interface token',\n hint: `remove provider ${providerId} or the existing provider for ${token} and retry`,\n detail: { token, providerId },\n };\n}\n\nfunction availableProvider<K extends VfxDataInterfaceKind>(\n token: VfxDataInterfaceProvider<K>['token'],\n kind: K,\n bindingType: VfxDataInterfaceProvider<K>['bindingType'],\n source: VfxDataInterfaceAvailabilitySource,\n): VfxDataInterfaceProvider<K> {\n return {\n id: `${token}-provider`,\n token,\n kind,\n bindingType,\n provide: (generation) => {\n if (!source.available(generation)) {\n return err({\n code: 'vfx-data-interface-missing',\n expected: `an available ${kind} provider for ${token}`,\n hint: `make ${token} available for generation ${generation} and retry rendering`,\n detail: { token, providerId: `${token}-provider` },\n });\n }\n const resource: VfxDataInterfaceResource = {\n token,\n kind,\n bindingType,\n generation,\n };\n return ok(resource);\n },\n };\n}\n\nexport function createCameraProvider(\n source: VfxDataInterfaceAvailabilitySource,\n): VfxDataInterfaceProvider<'camera'> {\n return availableProvider('vfx:camera', 'camera', 'uniform', source);\n}\n\nexport function createSceneDepthProvider(\n source: VfxDataInterfaceAvailabilitySource,\n): VfxDataInterfaceProvider<'scene-depth'> {\n return availableProvider('vfx:scene-depth', 'scene-depth', 'sampled-depth', source);\n}\n\nexport function createVfxDataInterfaceRegistry(\n initialProviders: readonly VfxDataInterfaceProvider[] = [],\n): VfxDataInterfaceRegistry {\n const entries = new Map<VfxDataInterfaceToken, VfxDataInterfaceProvider>();\n let registrationError: VfxDataInterfaceError | undefined;\n let lastSnapshot: VfxDataInterfaceRegistry['snapshot'];\n const registry: VfxDataInterfaceRegistry = {\n get providers() {\n return Object.freeze([...entries.values()]);\n },\n get snapshot() {\n return lastSnapshot;\n },\n register(provider) {\n if (entries.has(provider.token)) {\n const error = duplicate(provider.token, provider.id);\n registrationError ??= error;\n return err(error);\n }\n entries.set(provider.token, provider);\n return ok(undefined);\n },\n resolve(requirements, generation) {\n const result =\n registrationError === undefined\n ? resolveVfxDataInterfaces(requirements, [...entries.values()], generation)\n : err(registrationError);\n lastSnapshot = Object.freeze({ generation, result });\n return result;\n },\n };\n for (const provider of initialProviders) registry.register(provider);\n return registry;\n}\n","import type {\n AssetRegistryResolver,\n AssetRegistry as LegacyAssetRegistry,\n RuntimeAssetRegistry,\n} from '@forgeax/engine-assets-runtime';\nimport { getAssetRegistryResolver } from '@forgeax/engine-assets-runtime';\nimport { createWorldContext, type EntityHandle, type World } from '@forgeax/engine-ecs';\nimport type {\n Asset,\n AssetDecoderLease,\n MaterialAsset,\n MeshAsset,\n Result,\n} from '@forgeax/engine-types';\nimport { err, ok } from '@forgeax/engine-types';\nimport type {\n VfxDataInterfaceError,\n VfxDataInterfaceProvider,\n VfxDataInterfaceRequirement,\n VfxDataInterfaceResolution,\n VfxGpuPlayerInspectSnapshot,\n VfxGpuRuntimeDiagnostic,\n VfxReplayInput,\n VfxValueMap,\n} from '@forgeax/engine-vfx';\nimport {\n ParticleEffectPlayer,\n VFX_GPU_RUNTIME_RESOURCE_KEY,\n type VfxGpuRuntime,\n vfxGpuEffectContribution,\n vfxGpuEffectPackLoader,\n vfxGpuRuntimePlugin,\n} from '@forgeax/engine-vfx';\nimport type { ParticleRenderCameraSource } from '../feature/camera.js';\nimport { gpuParticleRenderFeature } from '../feature/gpu-particle-feature.js';\nimport {\n createVfxDataInterfaceRegistry,\n type VfxDataInterfaceRegistry,\n} from './data-interface-providers.js';\n\n/**\n * Public authoring projection accepted by the VFX host. Editor owns the\n * projection, while the Engine App still owns bytes/decoders/cache. Keeping\n * this small structural seam public lets the Editor pass that projection\n * without importing the runtime registry's internal module or fabricating a\n * second registry identity.\n */\nexport interface VfxAuthoringAssetRegistry {\n readonly loaders: {\n registerPackLoader(loader: unknown): void;\n };\n lookup<T extends Asset = Asset>(guid: string): T | undefined;\n readonly load?: (guid: string, kind: string) => Promise<Result<unknown, unknown>>;\n}\n\ntype AssetRegistry = LegacyAssetRegistry | RuntimeAssetRegistry | VfxAuthoringAssetRegistry;\n\nexport interface VfxRuntimeHostOptions {\n readonly camera: ParticleRenderCameraSource;\n readonly maxQueuedTicks?: number;\n readonly providers?: readonly VfxDataInterfaceProvider[];\n}\n\nexport interface VfxRuntimeHostError {\n readonly code:\n | 'vfx-host-loader-install-failed'\n | 'vfx-host-world-attach-failed'\n | 'vfx-host-world-detach-failed';\n readonly expected: string;\n readonly hint: string;\n readonly detail: { readonly cause: unknown };\n}\n\nexport interface VfxRuntimeHostControlError {\n readonly code:\n | 'vfx-host-control-world-detached'\n | 'vfx-host-control-stale-generation'\n | 'vfx-host-control-runtime-unavailable'\n | 'vfx-host-control-player-unavailable';\n readonly expected: string;\n readonly hint: string;\n readonly detail: {\n readonly requestedGeneration?: number;\n readonly currentGeneration?: number;\n readonly player?: EntityHandle;\n };\n}\n\nexport interface VfxRuntimeHostControl {\n readonly generation: number;\n replay(input: {\n readonly player: EntityHandle;\n readonly replayInput?: VfxReplayInput<VfxValueMap>;\n }): Result<{ readonly state: 'queued'; readonly generation: number }, VfxRuntimeHostControlError>;\n setEmitterSessionEnabled(input: {\n readonly player: EntityHandle;\n readonly emitterId: string;\n readonly enabled: boolean;\n }): Result<\n {\n readonly state: 'enabled' | 'disabled';\n readonly generation: number;\n },\n VfxRuntimeHostControlError\n >;\n setPlayerRenderConsumption(input: {\n readonly player: EntityHandle;\n readonly enabled: boolean;\n }): Result<\n {\n readonly state: 'enabled' | 'paused';\n readonly generation: number;\n },\n VfxRuntimeHostControlError\n >;\n}\n\nexport interface VfxRuntimeHost {\n readonly feature: ReturnType<typeof gpuParticleRenderFeature>;\n readonly dataInterfaces: VfxDataInterfaceRegistry;\n inspect(world: World): VfxRuntimeHostInspectSnapshot | undefined;\n acquireControl(world: World): Result<VfxRuntimeHostControl, VfxRuntimeHostControlError>;\n resolveDataInterfaces(input: {\n readonly requirements: readonly VfxDataInterfaceRequirement[];\n readonly generation: number;\n }): Result<VfxDataInterfaceResolution, VfxDataInterfaceError>;\n attachWorld(input: {\n readonly world: World;\n readonly assets: AssetRegistry;\n }): Promise<Result<{ readonly state: 'attached' | 'already-attached' }, VfxRuntimeHostError>>;\n detachWorld(input: {\n readonly world: World;\n }): Promise<Result<{ readonly state: 'detached' | 'not-attached' }, VfxRuntimeHostError>>;\n}\n\n/** Install the VFX owner decoder into the core registry. */\nexport function installVfxRuntimeDecoder(registry: RuntimeAssetRegistry): AssetDecoderLease {\n return registry.installDecoder(vfxGpuEffectContribution.kind, vfxGpuEffectContribution.decoder);\n}\n\nexport interface VfxRuntimeHostInspectSnapshot {\n readonly generation: number;\n /** VFX GPU resource generation; distinct from host attachment generation. */\n readonly renderGeneration: number;\n readonly players: readonly VfxGpuPlayerInspectSnapshot[];\n readonly diagnostics: readonly VfxGpuRuntimeDiagnostic[];\n}\n\ntype PluginContext = Awaited<ReturnType<typeof createWorldContext>>;\n\nfunction failure(\n code: VfxRuntimeHostError['code'],\n expected: string,\n hint: string,\n cause: unknown,\n): VfxRuntimeHostError {\n return { code, expected, hint, detail: { cause } };\n}\n\nfunction controlFailure(\n code: VfxRuntimeHostControlError['code'],\n expected: string,\n hint: string,\n detail: VfxRuntimeHostControlError['detail'] = {},\n): VfxRuntimeHostControlError {\n return { code, expected, hint, detail };\n}\n\nexport function createVfxRuntimeHost(options: VfxRuntimeHostOptions): VfxRuntimeHost {\n const registries = new WeakSet<AssetRegistry>();\n const worlds = new WeakMap<\n World,\n {\n readonly assets: AssetRegistry;\n readonly resolver: AssetRegistryResolver | undefined;\n readonly generation: number;\n readonly pluginContext: PluginContext;\n readonly renderAssets: Map<string, MaterialAsset | MeshAsset>;\n readonly pendingRenderAssets: Map<string, Promise<void>>;\n readonly unsubscribeAssets: () => void;\n catalogEpoch: number;\n }\n >();\n const pausedPlayers = new WeakMap<World, Set<EntityHandle>>();\n let nextGeneration = 1;\n const dataInterfaces = createVfxDataInterfaceRegistry(options.providers);\n const readRenderAsset = <Kind extends 'material' | 'mesh'>(\n world: World,\n guid: string,\n kind: Kind,\n ): (Kind extends 'material' ? MaterialAsset : MeshAsset) | undefined => {\n const attached = worlds.get(world);\n if (attached === undefined) return undefined;\n const key = `${kind}:${guid.toLowerCase()}`;\n const cached = attached.renderAssets.get(key);\n if (cached?.kind === kind) return cached as Kind extends 'material' ? MaterialAsset : MeshAsset;\n if ('lookup' in attached.assets) {\n const lookup = attached.assets.lookup as (guid: string) => Asset | undefined;\n // Preserve the registry receiver: the Engine-owned legacy class uses\n // `this` to read its load-state/catalogue maps. The Editor facade may\n // expose an arrow function, but calling through the owner is safe for\n // both shapes and avoids turning a lookup into a swallowed plan error.\n const legacy = lookup.call(attached.assets, guid);\n if (legacy?.kind === kind) {\n attached.renderAssets.set(key, legacy);\n return legacy as Kind extends 'material' ? MaterialAsset : MeshAsset;\n }\n }\n const resolved = attached.resolver?.lookup<MaterialAsset | MeshAsset>(guid);\n if (resolved?.kind === kind) {\n attached.renderAssets.set(key, resolved);\n return resolved as Kind extends 'material' ? MaterialAsset : MeshAsset;\n }\n if (\n 'load' in attached.assets &&\n typeof attached.assets.load === 'function' &&\n !attached.pendingRenderAssets.has(key)\n ) {\n const epoch = attached.catalogEpoch;\n const load = attached.assets.load as (\n guid: string,\n kind: string,\n ) => Promise<Result<MaterialAsset | MeshAsset, unknown>>;\n const request = load(guid, kind)\n .then((result) => {\n if (!result.ok || worlds.get(world) !== attached || attached.catalogEpoch !== epoch)\n return;\n attached.renderAssets.set(key, result.value);\n })\n .catch(() => undefined);\n attached.pendingRenderAssets.set(key, request);\n void request.finally(() => {\n if (attached.pendingRenderAssets.get(key) === request) {\n attached.pendingRenderAssets.delete(key);\n }\n });\n }\n return undefined;\n };\n const feature = gpuParticleRenderFeature({\n camera: options.camera,\n dataInterfaces,\n material: { read: (world, guid) => readRenderAsset(world, guid, 'material') },\n mesh: { read: (world, guid) => readRenderAsset(world, guid, 'mesh') },\n playerConsumption: {\n isEnabled: (world, player) => !pausedPlayers.get(world)?.has(player),\n },\n });\n return {\n feature,\n dataInterfaces,\n inspect: (world) => {\n const attached = worlds.get(world);\n if (attached === undefined || !world.hasResource(VFX_GPU_RUNTIME_RESOURCE_KEY))\n return undefined;\n const runtime = world.getResource<VfxGpuRuntime>(VFX_GPU_RUNTIME_RESOURCE_KEY);\n return Object.freeze({\n generation: attached.generation,\n renderGeneration: runtime.renderGeneration,\n players: runtime.inspectPlayers(),\n diagnostics: runtime.diagnostics(),\n });\n },\n acquireControl: (world) => {\n const attached = worlds.get(world);\n if (attached === undefined) {\n return err(\n controlFailure(\n 'vfx-host-control-world-detached',\n 'an attached VFX Runtime World',\n 'attach the World to this VfxRuntimeHost before acquiring controls',\n ),\n );\n }\n const requestedGeneration = attached.generation;\n const withRuntime = <T>(\n player: EntityHandle,\n action: (runtime: VfxGpuRuntime) => T,\n ): Result<T, VfxRuntimeHostControlError> => {\n const current = worlds.get(world);\n if (current === undefined) {\n return err(\n controlFailure(\n 'vfx-host-control-world-detached',\n `VFX host generation ${requestedGeneration} to remain attached`,\n 'reacquire controls after the World is attached again',\n { requestedGeneration },\n ),\n );\n }\n if (current.generation !== requestedGeneration) {\n return err(\n controlFailure(\n 'vfx-host-control-stale-generation',\n `VFX host generation ${requestedGeneration}`,\n 'discard this stale control lease and acquire one from the current host generation',\n { requestedGeneration, currentGeneration: current.generation },\n ),\n );\n }\n if (!world.hasResource(VFX_GPU_RUNTIME_RESOURCE_KEY)) {\n return err(\n controlFailure(\n 'vfx-host-control-runtime-unavailable',\n 'the attached World to own its VFX GPU runtime resource',\n 'repair the host attachment before retrying the preview command',\n { requestedGeneration, currentGeneration: current.generation },\n ),\n );\n }\n if (!world.get(player, ParticleEffectPlayer).ok) {\n return err(\n controlFailure(\n 'vfx-host-control-player-unavailable',\n 'a live entity with ParticleEffectPlayer in the attached World',\n 'discard the stale player handle or target a VFX player owned by this World',\n { requestedGeneration, currentGeneration: current.generation, player },\n ),\n );\n }\n return ok(action(world.getResource<VfxGpuRuntime>(VFX_GPU_RUNTIME_RESOURCE_KEY)));\n };\n const control: VfxRuntimeHostControl = {\n generation: requestedGeneration,\n replay: ({ player, replayInput }) =>\n withRuntime(player, (runtime) => {\n runtime.replay(player, replayInput);\n return Object.freeze({ state: 'queued' as const, generation: requestedGeneration });\n }),\n setEmitterSessionEnabled: ({ player, emitterId, enabled }) =>\n withRuntime(player, (runtime) => {\n runtime.setEmitterSessionEnabled(player, emitterId, enabled);\n return Object.freeze({\n state: enabled ? ('enabled' as const) : ('disabled' as const),\n generation: requestedGeneration,\n });\n }),\n setPlayerRenderConsumption: ({ player, enabled }) =>\n withRuntime(player, () => {\n let paused = pausedPlayers.get(world);\n if (enabled) {\n paused?.delete(player);\n if (paused !== undefined && paused.size === 0) pausedPlayers.delete(world);\n } else {\n paused ??= new Set();\n paused.add(player);\n pausedPlayers.set(world, paused);\n }\n return Object.freeze({\n state: enabled ? ('enabled' as const) : ('paused' as const),\n generation: requestedGeneration,\n });\n }),\n };\n return ok(Object.freeze(control));\n },\n resolveDataInterfaces: ({ requirements, generation }) =>\n dataInterfaces.resolve(requirements, generation),\n attachWorld: async ({ world, assets }) => {\n if (worlds.has(world)) return ok({ state: 'already-attached' });\n if (!registries.has(assets)) {\n try {\n // The Editor facade deliberately exposes the legacy LoaderRegistry\n // while projecting the Engine-owned App.assets instance. Prefer\n // that public authoring seam before looking for the five-action\n // runtime registry; otherwise a facade that happens to expose\n // `load` would be misclassified as a decoder owner.\n if ('loaders' in assets) {\n assets.loaders.registerPackLoader(vfxGpuEffectPackLoader);\n } else if ('installDecoder' in assets) {\n assets.installDecoder(vfxGpuEffectContribution.kind, vfxGpuEffectContribution.decoder);\n } else {\n throw new TypeError('VFX assets registry exposes neither loaders nor installDecoder');\n }\n registries.add(assets);\n } catch (cause) {\n return err(\n failure(\n 'vfx-host-loader-install-failed',\n 'the v2 VFX loader to be registered once',\n 'remove a conflicting particle-effect loader and retry attachWorld',\n cause,\n ),\n );\n }\n }\n let pluginContext: PluginContext;\n try {\n pluginContext = await createWorldContext(world, [\n vfxGpuRuntimePlugin(\n options.maxQueuedTicks === undefined ? {} : { maxQueuedTicks: options.maxQueuedTicks },\n ),\n ]);\n } catch (cause) {\n return err(\n failure(\n 'vfx-host-world-attach-failed',\n 'the World FixedUpdate VFX intent producer to install',\n 'repair the reported World registration conflict and retry',\n cause,\n ),\n );\n }\n let resolver: AssetRegistryResolver | undefined;\n if (!('loaders' in assets) && 'installDecoder' in assets) {\n try {\n resolver = getAssetRegistryResolver(assets);\n } catch {\n resolver = undefined;\n }\n }\n const attached = {\n assets,\n resolver,\n pluginContext,\n generation: nextGeneration++,\n renderAssets: new Map<string, MaterialAsset | MeshAsset>(),\n pendingRenderAssets: new Map<string, Promise<void>>(),\n catalogEpoch:\n 'snapshot' in assets && typeof assets.snapshot === 'function'\n ? assets.snapshot().epoch\n : 0,\n unsubscribeAssets: () => {},\n };\n if ('subscribe' in assets && typeof assets.subscribe === 'function') {\n attached.unsubscribeAssets = assets.subscribe((snapshot) => {\n if (snapshot.epoch === attached.catalogEpoch) return;\n attached.catalogEpoch = snapshot.epoch;\n attached.renderAssets.clear();\n attached.pendingRenderAssets.clear();\n });\n }\n worlds.set(world, attached);\n return ok({ state: 'attached' });\n },\n detachWorld: async ({ world }) => {\n const attached = worlds.get(world);\n if (attached === undefined) return ok({ state: 'not-attached' });\n try {\n await attached.pluginContext.fiber.dispose();\n } catch (cause) {\n return err(\n failure(\n 'vfx-host-world-detach-failed',\n 'the VFX FixedUpdate producer to detach exactly once',\n 'inspect the World schedule and retry detachWorld',\n cause,\n ),\n );\n }\n pausedPlayers.delete(world);\n attached.unsubscribeAssets();\n attached.renderAssets.clear();\n attached.pendingRenderAssets.clear();\n worlds.delete(world);\n return ok({ state: 'detached' });\n },\n };\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forgeax/engine-vfx-render",
3
- "version": "0.1.23",
3
+ "version": "0.1.24",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -22,13 +22,13 @@
22
22
  "LICENSE"
23
23
  ],
24
24
  "dependencies": {
25
- "@forgeax/engine-assets-runtime": "0.1.23",
26
- "@forgeax/engine-ecs": "0.1.23",
27
- "@forgeax/engine-math": "0.1.23",
28
- "@forgeax/engine-render": "0.1.23",
29
- "@forgeax/engine-scene": "0.1.23",
30
- "@forgeax/engine-types": "0.1.23",
31
- "@forgeax/engine-vfx": "0.1.23"
25
+ "@forgeax/engine-assets-runtime": "0.1.24",
26
+ "@forgeax/engine-ecs": "0.1.24",
27
+ "@forgeax/engine-math": "0.1.24",
28
+ "@forgeax/engine-render": "0.1.24",
29
+ "@forgeax/engine-scene": "0.1.24",
30
+ "@forgeax/engine-types": "0.1.24",
31
+ "@forgeax/engine-vfx": "0.1.24"
32
32
  },
33
33
  "devDependencies": {},
34
34
  "forgeax": {