@plasius/gpu-renderer 0.1.6 → 0.1.8

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.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.js"],"sourcesContent":["const DEFAULT_CLEAR_COLOR = Object.freeze([0.07, 0.11, 0.18, 1.0]);\nconst DEFAULT_CANVAS_SELECTOR = \"canvas[data-plasius-gpu-renderer]\";\n\nfunction clamp01(value) {\n return Math.min(1, Math.max(0, value));\n}\n\nfunction parseHexChannel(channel) {\n return parseInt(channel, 16) / 255;\n}\n\nfunction normalizeColor(value) {\n if (Array.isArray(value)) {\n const [r = 0, g = 0, b = 0, a = 1] = value;\n return [clamp01(Number(r) || 0), clamp01(Number(g) || 0), clamp01(Number(b) || 0), clamp01(Number(a) || 0)];\n }\n\n if (typeof value === \"string\") {\n const trimmed = value.trim();\n if (/^#[0-9a-f]{3}$/i.test(trimmed)) {\n const r = trimmed[1];\n const g = trimmed[2];\n const b = trimmed[3];\n return [\n parseHexChannel(r + r),\n parseHexChannel(g + g),\n parseHexChannel(b + b),\n 1,\n ];\n }\n if (/^#[0-9a-f]{6}$/i.test(trimmed)) {\n return [\n parseHexChannel(trimmed.slice(1, 3)),\n parseHexChannel(trimmed.slice(3, 5)),\n parseHexChannel(trimmed.slice(5, 7)),\n 1,\n ];\n }\n }\n\n return [...DEFAULT_CLEAR_COLOR];\n}\n\nfunction now() {\n if (typeof performance !== \"undefined\" && typeof performance.now === \"function\") {\n return performance.now();\n }\n return Date.now();\n}\n\nfunction readNavigator(navigatorOverride) {\n const currentNavigator = navigatorOverride ?? globalThis.navigator;\n if (!currentNavigator || typeof currentNavigator !== \"object\") {\n throw new Error(\"Navigator unavailable. Provide a browser-like navigator object.\");\n }\n return currentNavigator;\n}\n\nfunction readDocument(documentOverride) {\n const doc = documentOverride ?? globalThis.document;\n if (!doc || typeof doc !== \"object\") {\n throw new Error(\"Document unavailable. Provide a browser-like document object.\");\n }\n return doc;\n}\n\nfunction resolveCanvas(canvasOrSelector, documentOverride) {\n if (canvasOrSelector && typeof canvasOrSelector === \"object\") {\n return canvasOrSelector;\n }\n\n const doc = readDocument(documentOverride);\n const selector =\n typeof canvasOrSelector === \"string\" && canvasOrSelector.trim().length > 0\n ? canvasOrSelector\n : DEFAULT_CANVAS_SELECTOR;\n const resolved = doc.querySelector(selector);\n if (!resolved) {\n throw new Error(`Unable to find canvas for selector \"${selector}\".`);\n }\n return resolved;\n}\n\nfunction readGpu(navigatorOverride) {\n const currentNavigator = readNavigator(navigatorOverride);\n const gpu = currentNavigator.gpu;\n if (!gpu || typeof gpu.requestAdapter !== \"function\") {\n throw new Error(\"WebGPU runtime unavailable. navigator.gpu is missing.\");\n }\n return gpu;\n}\n\nfunction configureContext(context, device, format, alphaMode) {\n if (typeof context.configure !== \"function\") {\n throw new Error(\"Canvas WebGPU context does not support configure().\");\n }\n context.configure({\n device,\n format,\n alphaMode,\n });\n}\n\nfunction createRenderPassDescriptor(view, clearColor) {\n return {\n colorAttachments: [\n {\n view,\n loadOp: \"clear\",\n clearValue: {\n r: clearColor[0],\n g: clearColor[1],\n b: clearColor[2],\n a: clearColor[3],\n },\n storeOp: \"store\",\n },\n ],\n };\n}\n\nexport function supportsWebGpu(options = {}) {\n try {\n const gpu = readGpu(options.navigator);\n return Boolean(gpu);\n } catch {\n return false;\n }\n}\n\nexport async function createGpuRenderer(options = {}) {\n const {\n canvas,\n navigator: navigatorOverride,\n document: documentOverride,\n powerPreference = \"high-performance\",\n alpha = true,\n format,\n clearColor = DEFAULT_CLEAR_COLOR,\n requestAnimationFrame = globalThis.requestAnimationFrame?.bind(globalThis),\n cancelAnimationFrame = globalThis.cancelAnimationFrame?.bind(globalThis),\n onBeforeEncode,\n onAfterSubmit,\n } = options;\n\n const gpu = readGpu(navigatorOverride);\n const adapter = await gpu.requestAdapter({ powerPreference });\n if (!adapter) {\n throw new Error(\"Unable to obtain GPU adapter.\");\n }\n\n const device = await adapter.requestDevice();\n const targetCanvas = resolveCanvas(canvas, documentOverride);\n const context = targetCanvas.getContext?.(\"webgpu\");\n if (!context) {\n throw new Error(\"Unable to obtain WebGPU canvas context.\");\n }\n\n const resolvedFormat =\n format ||\n (typeof gpu.getPreferredCanvasFormat === \"function\"\n ? gpu.getPreferredCanvasFormat()\n : \"bgra8unorm\");\n\n configureContext(context, device, resolvedFormat, alpha ? \"premultiplied\" : \"opaque\");\n\n let running = false;\n let destroyed = false;\n let frame = 0;\n let lastTimestamp = 0;\n let rafId = null;\n let clear = normalizeColor(clearColor);\n let xrActive = false;\n let detachXrBinding = null;\n\n const renderOnce = (timestamp = now()) => {\n if (destroyed) {\n throw new Error(\"Renderer was destroyed.\");\n }\n\n const texture = context.getCurrentTexture?.();\n if (!texture || typeof texture.createView !== \"function\") {\n throw new Error(\"WebGPU context returned an invalid current texture.\");\n }\n\n const encoder = device.createCommandEncoder({\n label: `plasius.gpu-renderer.frame.${frame}`,\n });\n const view = texture.createView();\n\n const pass = encoder.beginRenderPass(createRenderPassDescriptor(view, clear));\n\n if (typeof onBeforeEncode === \"function\") {\n onBeforeEncode({\n frame,\n timestamp,\n device,\n context,\n encoder,\n pass,\n canvas: targetCanvas,\n });\n }\n\n if (typeof pass.end === \"function\") {\n pass.end();\n }\n\n const commandBuffer = encoder.finish();\n device.queue.submit([commandBuffer]);\n\n frame += 1;\n lastTimestamp = timestamp;\n\n if (typeof onAfterSubmit === \"function\") {\n onAfterSubmit({\n frame,\n timestamp,\n device,\n context,\n canvas: targetCanvas,\n });\n }\n\n return {\n frame,\n timestamp,\n };\n };\n\n const tick = (timestamp) => {\n if (!running || destroyed) {\n return;\n }\n renderOnce(timestamp);\n if (typeof requestAnimationFrame === \"function\") {\n rafId = requestAnimationFrame(tick);\n }\n };\n\n const start = () => {\n if (destroyed) {\n throw new Error(\"Renderer was destroyed.\");\n }\n if (running) {\n return false;\n }\n running = true;\n if (typeof requestAnimationFrame === \"function\") {\n rafId = requestAnimationFrame(tick);\n } else {\n renderOnce();\n }\n return true;\n };\n\n const stop = () => {\n if (!running) {\n return false;\n }\n running = false;\n if (rafId !== null && typeof cancelAnimationFrame === \"function\") {\n cancelAnimationFrame(rafId);\n }\n rafId = null;\n return true;\n };\n\n const resize = (cssWidth, cssHeight, devicePixelRatio = globalThis.devicePixelRatio ?? 1) => {\n const width = Math.max(1, Math.floor(cssWidth * devicePixelRatio));\n const height = Math.max(1, Math.floor(cssHeight * devicePixelRatio));\n targetCanvas.width = width;\n targetCanvas.height = height;\n if (targetCanvas.style) {\n targetCanvas.style.width = `${Math.max(1, Math.floor(cssWidth))}px`;\n targetCanvas.style.height = `${Math.max(1, Math.floor(cssHeight))}px`;\n }\n return { width, height };\n };\n\n const setClearColor = (value) => {\n clear = normalizeColor(value);\n return [...clear];\n };\n\n const setXrActive = (active) => {\n xrActive = Boolean(active);\n };\n\n const getSnapshot = () => {\n const width = Number(targetCanvas.width) || 0;\n const height = Number(targetCanvas.height) || 0;\n return {\n running,\n frame,\n lastTimestamp,\n format: resolvedFormat,\n width,\n height,\n xrActive,\n };\n };\n\n const renderer = {\n canvas: targetCanvas,\n context,\n device,\n format: resolvedFormat,\n renderOnce,\n start,\n stop,\n resize,\n setClearColor,\n setXrActive,\n getSnapshot,\n bindXrManager(xrManager, bindOptions = {}) {\n if (detachXrBinding) {\n detachXrBinding();\n }\n detachXrBinding = bindRendererToXrManager(renderer, xrManager, bindOptions);\n return detachXrBinding;\n },\n destroy() {\n stop();\n destroyed = true;\n if (detachXrBinding) {\n detachXrBinding();\n detachXrBinding = null;\n }\n if (typeof context.unconfigure === \"function\") {\n context.unconfigure();\n }\n },\n };\n\n return renderer;\n}\n\nfunction snapshotFromXrManager(xrManager) {\n if (xrManager && typeof xrManager.getState === \"function\") {\n return xrManager.getState();\n }\n if (xrManager?.store && typeof xrManager.store.getSnapshot === \"function\") {\n return xrManager.store.getSnapshot();\n }\n return null;\n}\n\nexport function bindRendererToXrManager(renderer, xrManager, options = {}) {\n if (!xrManager || typeof xrManager.subscribe !== \"function\") {\n throw new Error(\"XR manager must expose subscribe(listener). Use @plasius/gpu-xr createXrManager().\");\n }\n\n const { onSessionStart, onSessionEnd } = options;\n let previousSession = null;\n\n const applyState = (state) => {\n const session = state?.activeSession ?? null;\n if (session === previousSession) {\n return;\n }\n\n previousSession = session;\n\n if (typeof renderer.setXrActive === \"function\") {\n renderer.setXrActive(Boolean(session));\n }\n\n if (session && typeof onSessionStart === \"function\") {\n onSessionStart(session, renderer);\n }\n\n if (!session && typeof onSessionEnd === \"function\") {\n onSessionEnd(renderer);\n }\n };\n\n applyState(snapshotFromXrManager(xrManager));\n return xrManager.subscribe(applyState);\n}\n\nexport const defaultRendererClearColor = DEFAULT_CLEAR_COLOR;\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.js"],"sourcesContent":["const DEFAULT_CLEAR_COLOR = Object.freeze([0.07, 0.11, 0.18, 1.0]);\nconst DEFAULT_CANVAS_SELECTOR = \"canvas[data-plasius-gpu-renderer]\";\nexport const rendererDebugOwner = \"renderer\";\nexport const rendererWorkerQueueClass = \"render\";\nexport const defaultRendererWorkerProfile = \"realtime\";\nexport const rendererRepresentationBands = Object.freeze([\n \"near\",\n \"mid\",\n \"far\",\n \"horizon\",\n]);\nexport const rendererAccelerationStructureUpdateClasses = Object.freeze([\n \"static\",\n \"rigid-dynamic\",\n \"deforming\",\n \"proxy\",\n]);\nexport const rendererRayTracingStageOrder = Object.freeze([\n \"primaryVisibility\",\n \"shadowAssist\",\n \"opaqueFoundation\",\n \"rtDirectLighting\",\n \"rtReflections\",\n \"rtGlobalIllumination\",\n \"denoiseTemporal\",\n \"transparents\",\n \"composition\",\n \"present\",\n]);\n\nconst rendererRayTracingStageDefinitions = Object.freeze(\n rendererRayTracingStageOrder.map((key, index) =>\n Object.freeze({\n key,\n order: index + 1,\n required: true,\n description:\n {\n primaryVisibility: \"Primary visibility and depth preparation.\",\n shadowAssist: \"Shadow assist passes and regional shadow preparation.\",\n opaqueFoundation: \"Main opaque foundation for shading and tracing inputs.\",\n rtDirectLighting: \"Ray-traced direct lighting and premium shadows.\",\n rtReflections: \"Ray-traced reflections for important surfaces.\",\n rtGlobalIllumination: \"Selective ray-traced indirect lighting and GI.\",\n denoiseTemporal: \"Required denoise and temporal accumulation stage.\",\n transparents: \"Transparents, particles, and volumetrics composition.\",\n composition: \"Final world composition and color resolve.\",\n present: \"Presentation to the active surface.\",\n }[key],\n })\n )\n);\n\nconst rendererRepresentationBandPolicies = Object.freeze({\n near: Object.freeze({\n band: \"near\",\n rasterMode: \"full-live\",\n rtParticipation: \"premium\",\n shadowSource: \"ray-traced-primary\",\n temporalReuse: \"balanced\",\n updateCadenceDivisor: 1,\n }),\n mid: Object.freeze({\n band: \"mid\",\n rasterMode: \"simplified-live\",\n rtParticipation: \"selective\",\n shadowSource: \"regional-raster-and-proxy\",\n temporalReuse: \"aggressive\",\n updateCadenceDivisor: 2,\n }),\n far: Object.freeze({\n band: \"far\",\n rasterMode: \"proxy-or-cached\",\n rtParticipation: \"proxy\",\n shadowSource: \"merged-proxy-casters\",\n temporalReuse: \"high\",\n updateCadenceDivisor: 8,\n }),\n horizon: Object.freeze({\n band: \"horizon\",\n rasterMode: \"horizon-shell\",\n rtParticipation: \"disabled\",\n shadowSource: \"baked-impression\",\n temporalReuse: \"cached\",\n updateCadenceDivisor: 60,\n }),\n});\n\nconst rendererAccelerationStructurePolicies = Object.freeze(\n rendererAccelerationStructureUpdateClasses.map((updateClass) =>\n Object.freeze({\n updateClass,\n description:\n {\n static: \"Stable static world geometry with infrequent rebuilds.\",\n \"rigid-dynamic\":\n \"Rigid transforms that can be refit or relinked without full deformation updates.\",\n deforming:\n \"Skinned or vertex-deforming content treated as a managed RT cost center.\",\n proxy:\n \"Low-cost RT proxy or distant representation updates.\",\n }[updateClass],\n })\n )\n);\n\nfunction buildRendererWorkerBudgetLevels(jobType, queueClass, levels) {\n return Object.freeze(\n levels.map((level) =>\n Object.freeze({\n id: level.id,\n estimatedCostMs: level.estimatedCostMs,\n config: Object.freeze({\n maxDispatchesPerFrame: level.config.maxDispatchesPerFrame,\n maxJobsPerDispatch: level.config.maxJobsPerDispatch,\n cadenceDivisor: level.config.cadenceDivisor,\n workgroupScale: level.config.workgroupScale,\n maxQueueDepth: level.config.maxQueueDepth,\n metadata: Object.freeze({\n owner: rendererDebugOwner,\n queueClass,\n jobType,\n quality: level.id,\n }),\n }),\n })\n )\n );\n}\n\nconst rendererWorkerProfileSpecs = {\n realtime: {\n description:\n \"Frame-stage DAG for flat rendering with visibility, main encode, post-processing, and submit.\",\n suggestedAllocationIds: [\n \"renderer.surface.current\",\n \"renderer.visibility.worklist\",\n \"renderer.post-process.history\",\n ],\n jobs: {\n acquire: {\n priority: 5,\n dependencies: [],\n domain: \"resolution\",\n importance: \"critical\",\n levels: [\n {\n id: \"fixed\",\n estimatedCostMs: 0.2,\n config: {\n maxDispatchesPerFrame: 1,\n maxJobsPerDispatch: 1,\n cadenceDivisor: 1,\n workgroupScale: 1,\n maxQueueDepth: 1,\n },\n },\n ],\n suggestedAllocationIds: [\"renderer.surface.current\"],\n },\n visibility: {\n priority: 4,\n dependencies: [],\n domain: \"geometry\",\n importance: \"high\",\n levels: [\n {\n id: \"low\",\n estimatedCostMs: 0.4,\n config: {\n maxDispatchesPerFrame: 1,\n maxJobsPerDispatch: 128,\n cadenceDivisor: 2,\n workgroupScale: 0.5,\n maxQueueDepth: 256,\n },\n },\n {\n id: \"medium\",\n estimatedCostMs: 0.8,\n config: {\n maxDispatchesPerFrame: 1,\n maxJobsPerDispatch: 256,\n cadenceDivisor: 1,\n workgroupScale: 0.75,\n maxQueueDepth: 384,\n },\n },\n {\n id: \"high\",\n estimatedCostMs: 1.2,\n config: {\n maxDispatchesPerFrame: 2,\n maxJobsPerDispatch: 512,\n cadenceDivisor: 1,\n workgroupScale: 1,\n maxQueueDepth: 512,\n },\n },\n ],\n suggestedAllocationIds: [\"renderer.visibility.worklist\"],\n },\n mainEncode: {\n priority: 4,\n dependencies: [\"acquire\", \"visibility\"],\n domain: \"geometry\",\n importance: \"critical\",\n levels: [\n {\n id: \"low\",\n estimatedCostMs: 1.2,\n config: {\n maxDispatchesPerFrame: 1,\n maxJobsPerDispatch: 128,\n cadenceDivisor: 1,\n workgroupScale: 0.6,\n maxQueueDepth: 192,\n },\n },\n {\n id: \"medium\",\n estimatedCostMs: 2.1,\n config: {\n maxDispatchesPerFrame: 1,\n maxJobsPerDispatch: 256,\n cadenceDivisor: 1,\n workgroupScale: 0.8,\n maxQueueDepth: 256,\n },\n },\n {\n id: \"high\",\n estimatedCostMs: 3,\n config: {\n maxDispatchesPerFrame: 1,\n maxJobsPerDispatch: 384,\n cadenceDivisor: 1,\n workgroupScale: 1,\n maxQueueDepth: 384,\n },\n },\n ],\n suggestedAllocationIds: [\"renderer.surface.current\"],\n },\n postProcess: {\n priority: 3,\n dependencies: [\"mainEncode\"],\n domain: \"post-processing\",\n importance: \"high\",\n levels: [\n {\n id: \"low\",\n estimatedCostMs: 0.5,\n config: {\n maxDispatchesPerFrame: 1,\n maxJobsPerDispatch: 64,\n cadenceDivisor: 2,\n workgroupScale: 0.5,\n maxQueueDepth: 96,\n },\n },\n {\n id: \"medium\",\n estimatedCostMs: 0.9,\n config: {\n maxDispatchesPerFrame: 1,\n maxJobsPerDispatch: 128,\n cadenceDivisor: 1,\n workgroupScale: 0.75,\n maxQueueDepth: 128,\n },\n },\n {\n id: \"high\",\n estimatedCostMs: 1.4,\n config: {\n maxDispatchesPerFrame: 2,\n maxJobsPerDispatch: 192,\n cadenceDivisor: 1,\n workgroupScale: 1,\n maxQueueDepth: 192,\n },\n },\n ],\n suggestedAllocationIds: [\"renderer.post-process.history\"],\n },\n submit: {\n priority: 2,\n dependencies: [\"postProcess\"],\n domain: \"resolution\",\n importance: \"critical\",\n levels: [\n {\n id: \"fixed\",\n estimatedCostMs: 0.2,\n config: {\n maxDispatchesPerFrame: 1,\n maxJobsPerDispatch: 1,\n cadenceDivisor: 1,\n workgroupScale: 1,\n maxQueueDepth: 1,\n },\n },\n ],\n suggestedAllocationIds: [\"renderer.surface.current\"],\n },\n },\n },\n xr: {\n description:\n \"Frame-stage DAG for XR rendering with late-latch coordination before main encode and submit.\",\n suggestedAllocationIds: [\n \"renderer.xr.surface.current\",\n \"renderer.xr.visibility.worklist\",\n ],\n jobs: {\n acquire: {\n priority: 5,\n dependencies: [],\n domain: \"xr\",\n importance: \"critical\",\n levels: [\n {\n id: \"fixed\",\n estimatedCostMs: 0.2,\n config: {\n maxDispatchesPerFrame: 1,\n maxJobsPerDispatch: 1,\n cadenceDivisor: 1,\n workgroupScale: 1,\n maxQueueDepth: 1,\n },\n },\n ],\n suggestedAllocationIds: [\"renderer.xr.surface.current\"],\n },\n visibility: {\n priority: 4,\n dependencies: [],\n domain: \"geometry\",\n importance: \"high\",\n levels: [\n {\n id: \"low\",\n estimatedCostMs: 0.5,\n config: {\n maxDispatchesPerFrame: 1,\n maxJobsPerDispatch: 96,\n cadenceDivisor: 2,\n workgroupScale: 0.5,\n maxQueueDepth: 192,\n },\n },\n {\n id: \"medium\",\n estimatedCostMs: 0.9,\n config: {\n maxDispatchesPerFrame: 1,\n maxJobsPerDispatch: 192,\n cadenceDivisor: 1,\n workgroupScale: 0.75,\n maxQueueDepth: 256,\n },\n },\n {\n id: \"high\",\n estimatedCostMs: 1.3,\n config: {\n maxDispatchesPerFrame: 2,\n maxJobsPerDispatch: 320,\n cadenceDivisor: 1,\n workgroupScale: 1,\n maxQueueDepth: 320,\n },\n },\n ],\n suggestedAllocationIds: [\"renderer.xr.visibility.worklist\"],\n },\n lateLatch: {\n priority: 5,\n dependencies: [\"acquire\"],\n domain: \"xr\",\n importance: \"critical\",\n levels: [\n {\n id: \"fixed\",\n estimatedCostMs: 0.15,\n config: {\n maxDispatchesPerFrame: 1,\n maxJobsPerDispatch: 1,\n cadenceDivisor: 1,\n workgroupScale: 1,\n maxQueueDepth: 1,\n },\n },\n ],\n suggestedAllocationIds: [\"renderer.xr.surface.current\"],\n },\n mainEncode: {\n priority: 4,\n dependencies: [\"visibility\", \"lateLatch\"],\n domain: \"xr\",\n importance: \"critical\",\n levels: [\n {\n id: \"low\",\n estimatedCostMs: 1.1,\n config: {\n maxDispatchesPerFrame: 1,\n maxJobsPerDispatch: 96,\n cadenceDivisor: 1,\n workgroupScale: 0.6,\n maxQueueDepth: 128,\n },\n },\n {\n id: \"medium\",\n estimatedCostMs: 1.8,\n config: {\n maxDispatchesPerFrame: 1,\n maxJobsPerDispatch: 192,\n cadenceDivisor: 1,\n workgroupScale: 0.8,\n maxQueueDepth: 192,\n },\n },\n {\n id: \"high\",\n estimatedCostMs: 2.6,\n config: {\n maxDispatchesPerFrame: 1,\n maxJobsPerDispatch: 256,\n cadenceDivisor: 1,\n workgroupScale: 1,\n maxQueueDepth: 256,\n },\n },\n ],\n suggestedAllocationIds: [\"renderer.xr.surface.current\"],\n },\n submit: {\n priority: 2,\n dependencies: [\"mainEncode\"],\n domain: \"xr\",\n importance: \"critical\",\n levels: [\n {\n id: \"fixed\",\n estimatedCostMs: 0.2,\n config: {\n maxDispatchesPerFrame: 1,\n maxJobsPerDispatch: 1,\n cadenceDivisor: 1,\n workgroupScale: 1,\n maxQueueDepth: 1,\n },\n },\n ],\n suggestedAllocationIds: [\"renderer.xr.surface.current\"],\n },\n },\n },\n};\n\nfunction buildRendererInputBoundary(profile) {\n return Object.freeze({\n type: \"stable-visual-snapshot\",\n owner: rendererDebugOwner,\n profile,\n authority: \"visual\",\n source: \"scene-preparation\",\n stable: true,\n });\n}\n\nfunction buildRendererRenderStages(profile) {\n return Object.freeze(\n rendererRayTracingStageDefinitions.map((stage) =>\n Object.freeze({\n ...stage,\n profile,\n workerJobKeys:\n profile === \"xr\" && stage.key === \"primaryVisibility\"\n ? Object.freeze([\"lateLatch\", \"visibility\"])\n : stage.key === \"present\"\n ? Object.freeze([\"submit\"])\n : stage.key === \"denoiseTemporal\" ||\n stage.key === \"transparents\" ||\n stage.key === \"composition\"\n ? Object.freeze([\"postProcess\"])\n : stage.key === \"primaryVisibility\"\n ? Object.freeze([\"visibility\"])\n : stage.key === \"shadowAssist\" ||\n stage.key === \"opaqueFoundation\" ||\n stage.key === \"rtDirectLighting\" ||\n stage.key === \"rtReflections\" ||\n stage.key === \"rtGlobalIllumination\"\n ? Object.freeze([\"mainEncode\"])\n : Object.freeze([\"mainEncode\"]),\n })\n )\n );\n}\n\nfunction buildRendererRepresentationBands(profile) {\n return Object.freeze(\n rendererRepresentationBands.map((band) =>\n Object.freeze({\n ...rendererRepresentationBandPolicies[band],\n profile,\n })\n )\n );\n}\n\nfunction buildRendererAccelerationStructureUpdates(profile) {\n return Object.freeze(\n rendererAccelerationStructurePolicies.map((policy) =>\n Object.freeze({\n ...policy,\n profile,\n })\n )\n );\n}\n\nfunction assertRendererIdentifier(name, value) {\n if (typeof value !== \"string\" || value.trim().length === 0) {\n throw new Error(`${name} must be a non-empty string.`);\n }\n return value.trim();\n}\n\nfunction buildRendererWorkerProfile(name, spec) {\n return Object.freeze({\n name,\n description: spec.description,\n jobs: Object.freeze(Object.keys(spec.jobs)),\n });\n}\n\nfunction buildRendererWorkerManifestJob(profileName, jobName, spec) {\n const label = `renderer.${profileName}.${jobName}`;\n return Object.freeze({\n key: jobName,\n label,\n worker: Object.freeze({\n jobType: label,\n queueClass: rendererWorkerQueueClass,\n priority: spec.priority,\n dependencies: Object.freeze(\n spec.dependencies.map((dependency) => `renderer.${profileName}.${dependency}`)\n ),\n schedulerMode: \"dag\",\n }),\n performance: Object.freeze({\n id: label,\n jobType: label,\n queueClass: rendererWorkerQueueClass,\n domain: spec.domain,\n authority: \"visual\",\n importance: spec.importance,\n levels: buildRendererWorkerBudgetLevels(\n label,\n rendererWorkerQueueClass,\n spec.levels\n ),\n }),\n debug: Object.freeze({\n owner: rendererDebugOwner,\n queueClass: rendererWorkerQueueClass,\n jobType: label,\n tags: Object.freeze([\"renderer\", profileName, jobName, spec.domain]),\n suggestedAllocationIds: Object.freeze([...spec.suggestedAllocationIds]),\n }),\n });\n}\n\nfunction buildRendererWorkerManifest(name, spec) {\n return Object.freeze({\n schemaVersion: 1,\n owner: rendererDebugOwner,\n profile: name,\n description: spec.description,\n queueClass: rendererWorkerQueueClass,\n schedulerMode: \"dag\",\n inputBoundary: buildRendererInputBoundary(name),\n renderStages: buildRendererRenderStages(name),\n representationBands: buildRendererRepresentationBands(name),\n accelerationStructureUpdates: buildRendererAccelerationStructureUpdates(name),\n suggestedAllocationIds: Object.freeze([...spec.suggestedAllocationIds]),\n jobs: Object.freeze(\n Object.entries(spec.jobs).map(([jobName, jobSpec]) =>\n buildRendererWorkerManifestJob(name, jobName, jobSpec)\n )\n ),\n });\n}\n\nexport const rendererWorkerProfiles = Object.freeze(\n Object.fromEntries(\n Object.entries(rendererWorkerProfileSpecs).map(([name, spec]) => [\n name,\n buildRendererWorkerProfile(name, spec),\n ])\n )\n);\n\nexport const rendererWorkerProfileNames = Object.freeze(\n Object.keys(rendererWorkerProfiles)\n);\n\nexport const rendererWorkerManifests = Object.freeze(\n Object.fromEntries(\n Object.entries(rendererWorkerProfileSpecs).map(([name, spec]) => [\n name,\n buildRendererWorkerManifest(name, spec),\n ])\n )\n);\n\nexport function getRendererWorkerProfile(name = defaultRendererWorkerProfile) {\n const profile = rendererWorkerProfiles[name];\n if (!profile) {\n const available = rendererWorkerProfileNames.join(\", \");\n throw new Error(`Unknown renderer worker profile \"${name}\". Available: ${available}.`);\n }\n return profile;\n}\n\nexport function getRendererWorkerManifest(name = defaultRendererWorkerProfile) {\n const manifest = rendererWorkerManifests[name];\n if (!manifest) {\n const available = rendererWorkerProfileNames.join(\", \");\n throw new Error(`Unknown renderer worker profile \"${name}\". Available: ${available}.`);\n }\n return manifest;\n}\n\nexport function createRayTracingRenderPlan(options = {}) {\n const profile = options.profile ?? defaultRendererWorkerProfile;\n const snapshotId = assertRendererIdentifier(\n \"snapshotId\",\n options.snapshotId\n );\n const workerManifest = getRendererWorkerManifest(profile);\n const representations = Array.isArray(options.representations)\n ? Object.freeze(\n options.representations.map((representation, index) => {\n if (!representation || typeof representation !== \"object\") {\n throw new Error(`representations[${index}] must be an object.`);\n }\n const band = assertRendererIdentifier(\n `representations[${index}].band`,\n representation.band\n );\n if (!rendererRepresentationBands.includes(band)) {\n throw new Error(\n `representations[${index}].band must be one of: ${rendererRepresentationBands.join(\", \")}.`\n );\n }\n return Object.freeze({\n ...representation,\n band,\n });\n })\n )\n : workerManifest.representationBands;\n\n return Object.freeze({\n schemaVersion: 1,\n owner: rendererDebugOwner,\n profile,\n inputBoundary: Object.freeze({\n ...workerManifest.inputBoundary,\n snapshotId,\n }),\n renderStages: workerManifest.renderStages,\n representationBands: representations,\n accelerationStructureUpdates: workerManifest.accelerationStructureUpdates,\n workerManifest,\n });\n}\n\nfunction clamp01(value) {\n return Math.min(1, Math.max(0, value));\n}\n\nfunction parseHexChannel(channel) {\n return parseInt(channel, 16) / 255;\n}\n\nfunction normalizeColor(value) {\n if (Array.isArray(value)) {\n const [r = 0, g = 0, b = 0, a = 1] = value;\n return [clamp01(Number(r) || 0), clamp01(Number(g) || 0), clamp01(Number(b) || 0), clamp01(Number(a) || 0)];\n }\n\n if (typeof value === \"string\") {\n const trimmed = value.trim();\n if (/^#[0-9a-f]{3}$/i.test(trimmed)) {\n const r = trimmed[1];\n const g = trimmed[2];\n const b = trimmed[3];\n return [\n parseHexChannel(r + r),\n parseHexChannel(g + g),\n parseHexChannel(b + b),\n 1,\n ];\n }\n if (/^#[0-9a-f]{6}$/i.test(trimmed)) {\n return [\n parseHexChannel(trimmed.slice(1, 3)),\n parseHexChannel(trimmed.slice(3, 5)),\n parseHexChannel(trimmed.slice(5, 7)),\n 1,\n ];\n }\n }\n\n return [...DEFAULT_CLEAR_COLOR];\n}\n\nfunction readPositiveNumber(name, value) {\n if (value === undefined) {\n return undefined;\n }\n if (typeof value !== \"number\" || !Number.isFinite(value) || value <= 0) {\n throw new Error(`${name} must be a finite number greater than zero.`);\n }\n return value;\n}\n\nfunction now() {\n if (typeof performance !== \"undefined\" && typeof performance.now === \"function\") {\n return performance.now();\n }\n return Date.now();\n}\n\nfunction normalizeFrameId(value) {\n if (typeof value !== \"string\" || value.trim().length === 0) {\n throw new Error(\"frameIdFactory must return a non-empty string.\");\n }\n return value.trim();\n}\n\nfunction resolveTargetFrameTimeMs(options, event) {\n const {\n targetFrameTimeMs: fixedTargetFrameTimeMs,\n targetFrameRate,\n getTargetFrameTimeMs,\n } = options;\n\n if (typeof getTargetFrameTimeMs === \"function\") {\n const resolved = getTargetFrameTimeMs(event);\n return readPositiveNumber(\"getTargetFrameTimeMs()\", resolved);\n }\n\n if (fixedTargetFrameTimeMs !== undefined) {\n return fixedTargetFrameTimeMs;\n }\n\n if (targetFrameRate !== undefined) {\n return 1000 / targetFrameRate;\n }\n\n return undefined;\n}\n\nexport function createRendererDebugHooks(options = {}) {\n const {\n debugSession,\n targetFrameTimeMs,\n targetFrameRate,\n getTargetFrameTimeMs,\n onFrameStart,\n onFrameComplete,\n } = options;\n\n if (!debugSession || typeof debugSession.recordFrame !== \"function\") {\n throw new Error(\n \"debugSession must expose recordFrame(sample). Use @plasius/gpu-debug createGpuDebugSession().\"\n );\n }\n\n const fixedTargetFrameTimeMs = readPositiveNumber(\n \"targetFrameTimeMs\",\n targetFrameTimeMs\n );\n const fixedTargetFrameRate = readPositiveNumber(\n \"targetFrameRate\",\n targetFrameRate\n );\n\n if (\n fixedTargetFrameTimeMs !== undefined &&\n fixedTargetFrameRate !== undefined\n ) {\n throw new Error(\n \"Provide either targetFrameTimeMs or targetFrameRate, not both.\"\n );\n }\n\n if (\n getTargetFrameTimeMs !== undefined &&\n typeof getTargetFrameTimeMs !== \"function\"\n ) {\n throw new Error(\"getTargetFrameTimeMs must be a function when provided.\");\n }\n\n const resolvedOptions = {\n targetFrameTimeMs: fixedTargetFrameTimeMs,\n targetFrameRate: fixedTargetFrameRate,\n getTargetFrameTimeMs,\n };\n\n return {\n onFrameStart(event) {\n if (typeof onFrameStart === \"function\") {\n onFrameStart({\n ...event,\n owner: rendererDebugOwner,\n });\n }\n },\n onFrameComplete(event) {\n const resolvedTargetFrameTimeMs = resolveTargetFrameTimeMs(\n resolvedOptions,\n event\n );\n\n if (\n typeof event.frameTimeMs === \"number\" &&\n Number.isFinite(event.frameTimeMs) &&\n event.frameTimeMs > 0\n ) {\n debugSession.recordFrame({\n frameId: event.frameId,\n frameTimeMs: event.frameTimeMs,\n targetFrameTimeMs: resolvedTargetFrameTimeMs,\n });\n }\n\n if (typeof onFrameComplete === \"function\") {\n onFrameComplete({\n ...event,\n owner: rendererDebugOwner,\n targetFrameTimeMs: resolvedTargetFrameTimeMs,\n });\n }\n },\n };\n}\n\nfunction readNavigator(navigatorOverride) {\n const currentNavigator = navigatorOverride ?? globalThis.navigator;\n if (!currentNavigator || typeof currentNavigator !== \"object\") {\n throw new Error(\"Navigator unavailable. Provide a browser-like navigator object.\");\n }\n return currentNavigator;\n}\n\nfunction readDocument(documentOverride) {\n const doc = documentOverride ?? globalThis.document;\n if (!doc || typeof doc !== \"object\") {\n throw new Error(\"Document unavailable. Provide a browser-like document object.\");\n }\n return doc;\n}\n\nfunction resolveCanvas(canvasOrSelector, documentOverride) {\n if (canvasOrSelector && typeof canvasOrSelector === \"object\") {\n return canvasOrSelector;\n }\n\n const doc = readDocument(documentOverride);\n const selector =\n typeof canvasOrSelector === \"string\" && canvasOrSelector.trim().length > 0\n ? canvasOrSelector\n : DEFAULT_CANVAS_SELECTOR;\n const resolved = doc.querySelector(selector);\n if (!resolved) {\n throw new Error(`Unable to find canvas for selector \"${selector}\".`);\n }\n return resolved;\n}\n\nfunction readGpu(navigatorOverride) {\n const currentNavigator = readNavigator(navigatorOverride);\n const gpu = currentNavigator.gpu;\n if (!gpu || typeof gpu.requestAdapter !== \"function\") {\n throw new Error(\"WebGPU runtime unavailable. navigator.gpu is missing.\");\n }\n return gpu;\n}\n\nfunction configureContext(context, device, format, alphaMode) {\n if (typeof context.configure !== \"function\") {\n throw new Error(\"Canvas WebGPU context does not support configure().\");\n }\n context.configure({\n device,\n format,\n alphaMode,\n });\n}\n\nfunction createRenderPassDescriptor(view, clearColor) {\n return {\n colorAttachments: [\n {\n view,\n loadOp: \"clear\",\n clearValue: {\n r: clearColor[0],\n g: clearColor[1],\n b: clearColor[2],\n a: clearColor[3],\n },\n storeOp: \"store\",\n },\n ],\n };\n}\n\nexport function supportsWebGpu(options = {}) {\n try {\n const gpu = readGpu(options.navigator);\n return Boolean(gpu);\n } catch {\n return false;\n }\n}\n\nexport async function createGpuRenderer(options = {}) {\n const {\n canvas,\n navigator: navigatorOverride,\n document: documentOverride,\n powerPreference = \"high-performance\",\n alpha = true,\n format,\n clearColor = DEFAULT_CLEAR_COLOR,\n requestAnimationFrame = globalThis.requestAnimationFrame?.bind(globalThis),\n cancelAnimationFrame = globalThis.cancelAnimationFrame?.bind(globalThis),\n frameIdFactory,\n onFrameStart,\n onBeforeEncode,\n onAfterSubmit,\n onFrameComplete,\n } = options;\n\n const gpu = readGpu(navigatorOverride);\n const adapter = await gpu.requestAdapter({ powerPreference });\n if (!adapter) {\n throw new Error(\"Unable to obtain GPU adapter.\");\n }\n\n const device = await adapter.requestDevice();\n const targetCanvas = resolveCanvas(canvas, documentOverride);\n const context = targetCanvas.getContext?.(\"webgpu\");\n if (!context) {\n throw new Error(\"Unable to obtain WebGPU canvas context.\");\n }\n\n const resolvedFormat =\n format ||\n (typeof gpu.getPreferredCanvasFormat === \"function\"\n ? gpu.getPreferredCanvasFormat()\n : \"bgra8unorm\");\n\n configureContext(context, device, resolvedFormat, alpha ? \"premultiplied\" : \"opaque\");\n\n let running = false;\n let destroyed = false;\n let frame = 0;\n let lastTimestamp = 0;\n let rafId = null;\n let clear = normalizeColor(clearColor);\n let xrActive = false;\n let detachXrBinding = null;\n\n const renderOnce = (timestamp = now()) => {\n if (destroyed) {\n throw new Error(\"Renderer was destroyed.\");\n }\n\n const frameNumber = frame + 1;\n const frameId = normalizeFrameId(\n typeof frameIdFactory === \"function\"\n ? frameIdFactory({\n frame: frameNumber,\n timestamp,\n canvas: targetCanvas,\n xrActive,\n })\n : `renderer.frame.${frameNumber}`\n );\n const frameTimeMs =\n lastTimestamp > 0 ? Math.max(0, timestamp - lastTimestamp) : undefined;\n\n if (typeof onFrameStart === \"function\") {\n onFrameStart({\n frame: frameNumber,\n frameId,\n frameTimeMs,\n timestamp,\n device,\n context,\n canvas: targetCanvas,\n xrActive,\n });\n }\n\n const texture = context.getCurrentTexture?.();\n if (!texture || typeof texture.createView !== \"function\") {\n throw new Error(\"WebGPU context returned an invalid current texture.\");\n }\n\n const encoder = device.createCommandEncoder({\n label: `plasius.gpu-renderer.frame.${frame}`,\n });\n const view = texture.createView();\n\n const pass = encoder.beginRenderPass(createRenderPassDescriptor(view, clear));\n\n if (typeof onBeforeEncode === \"function\") {\n onBeforeEncode({\n frame,\n frameNumber,\n frameId,\n frameTimeMs,\n timestamp,\n device,\n context,\n encoder,\n pass,\n canvas: targetCanvas,\n xrActive,\n });\n }\n\n if (typeof pass.end === \"function\") {\n pass.end();\n }\n\n const commandBuffer = encoder.finish();\n device.queue.submit([commandBuffer]);\n\n frame = frameNumber;\n lastTimestamp = timestamp;\n\n if (typeof onAfterSubmit === \"function\") {\n onAfterSubmit({\n frame: frameNumber,\n frameNumber,\n frameId,\n frameTimeMs,\n timestamp,\n device,\n context,\n canvas: targetCanvas,\n xrActive,\n });\n }\n\n if (typeof onFrameComplete === \"function\") {\n onFrameComplete({\n frame: frameNumber,\n frameId,\n frameTimeMs,\n timestamp,\n device,\n context,\n canvas: targetCanvas,\n xrActive,\n });\n }\n\n return {\n frame: frameNumber,\n frameId,\n frameTimeMs,\n timestamp,\n };\n };\n\n const tick = (timestamp) => {\n if (!running || destroyed) {\n return;\n }\n renderOnce(timestamp);\n if (typeof requestAnimationFrame === \"function\") {\n rafId = requestAnimationFrame(tick);\n }\n };\n\n const start = () => {\n if (destroyed) {\n throw new Error(\"Renderer was destroyed.\");\n }\n if (running) {\n return false;\n }\n running = true;\n if (typeof requestAnimationFrame === \"function\") {\n rafId = requestAnimationFrame(tick);\n } else {\n renderOnce();\n }\n return true;\n };\n\n const stop = () => {\n if (!running) {\n return false;\n }\n running = false;\n if (rafId !== null && typeof cancelAnimationFrame === \"function\") {\n cancelAnimationFrame(rafId);\n }\n rafId = null;\n return true;\n };\n\n const resize = (cssWidth, cssHeight, devicePixelRatio = globalThis.devicePixelRatio ?? 1) => {\n const width = Math.max(1, Math.floor(cssWidth * devicePixelRatio));\n const height = Math.max(1, Math.floor(cssHeight * devicePixelRatio));\n targetCanvas.width = width;\n targetCanvas.height = height;\n if (targetCanvas.style) {\n targetCanvas.style.width = `${Math.max(1, Math.floor(cssWidth))}px`;\n targetCanvas.style.height = `${Math.max(1, Math.floor(cssHeight))}px`;\n }\n return { width, height };\n };\n\n const setClearColor = (value) => {\n clear = normalizeColor(value);\n return [...clear];\n };\n\n const setXrActive = (active) => {\n xrActive = Boolean(active);\n };\n\n const getSnapshot = () => {\n const width = Number(targetCanvas.width) || 0;\n const height = Number(targetCanvas.height) || 0;\n return {\n running,\n frame,\n lastTimestamp,\n format: resolvedFormat,\n width,\n height,\n xrActive,\n };\n };\n\n const renderer = {\n canvas: targetCanvas,\n context,\n device,\n format: resolvedFormat,\n renderOnce,\n start,\n stop,\n resize,\n setClearColor,\n setXrActive,\n getSnapshot,\n bindXrManager(xrManager, bindOptions = {}) {\n if (detachXrBinding) {\n detachXrBinding();\n }\n detachXrBinding = bindRendererToXrManager(renderer, xrManager, bindOptions);\n return detachXrBinding;\n },\n destroy() {\n stop();\n destroyed = true;\n if (detachXrBinding) {\n detachXrBinding();\n detachXrBinding = null;\n }\n if (typeof context.unconfigure === \"function\") {\n context.unconfigure();\n }\n },\n };\n\n return renderer;\n}\n\nfunction snapshotFromXrManager(xrManager) {\n if (xrManager && typeof xrManager.getState === \"function\") {\n return xrManager.getState();\n }\n if (xrManager?.store && typeof xrManager.store.getSnapshot === \"function\") {\n return xrManager.store.getSnapshot();\n }\n return null;\n}\n\nexport function bindRendererToXrManager(renderer, xrManager, options = {}) {\n if (!xrManager || typeof xrManager.subscribe !== \"function\") {\n throw new Error(\"XR manager must expose subscribe(listener). Use @plasius/gpu-xr createXrManager().\");\n }\n\n const { onSessionStart, onSessionEnd } = options;\n let previousSession = null;\n\n const applyState = (state) => {\n const session = state?.activeSession ?? null;\n if (session === previousSession) {\n return;\n }\n\n previousSession = session;\n\n if (typeof renderer.setXrActive === \"function\") {\n renderer.setXrActive(Boolean(session));\n }\n\n if (session && typeof onSessionStart === \"function\") {\n onSessionStart(session, renderer);\n }\n\n if (!session && typeof onSessionEnd === \"function\") {\n onSessionEnd(renderer);\n }\n };\n\n applyState(snapshotFromXrManager(xrManager));\n return xrManager.subscribe(applyState);\n}\n\nexport const defaultRendererClearColor = DEFAULT_CLEAR_COLOR;\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plasius/gpu-renderer",
3
- "version": "0.1.6",
3
+ "version": "0.1.8",
4
4
  "description": "Framework-agnostic WebGPU renderer runtime for Plasius projects.",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -49,7 +49,7 @@
49
49
  "author": "Plasius LTD <development@plasius.co.uk>",
50
50
  "license": "Apache-2.0",
51
51
  "dependencies": {
52
- "@plasius/gpu-xr": "^0.1.5"
52
+ "@plasius/gpu-xr": "^0.1.7"
53
53
  },
54
54
  "devDependencies": {
55
55
  "@eslint/js": "^9.39.1",
@@ -82,5 +82,8 @@
82
82
  ],
83
83
  "overrides": {
84
84
  "minimatch": "^10.2.1"
85
+ },
86
+ "engines": {
87
+ "node": ">=24"
85
88
  }
86
89
  }
package/src/index.d.ts CHANGED
@@ -1,5 +1,16 @@
1
1
  export type RendererColor = string | [number, number, number, number?];
2
2
 
3
+ export interface RendererFrameEvent {
4
+ frame: number;
5
+ frameId: string;
6
+ frameTimeMs?: number;
7
+ timestamp: number;
8
+ device: GPUDevice;
9
+ context: GPUCanvasContext;
10
+ canvas: HTMLCanvasElement;
11
+ xrActive: boolean;
12
+ }
13
+
3
14
  export interface RendererSnapshot {
4
15
  running: boolean;
5
16
  frame: number;
@@ -11,22 +22,32 @@ export interface RendererSnapshot {
11
22
  }
12
23
 
13
24
  export interface RendererHooks {
25
+ onFrameStart?: (event: RendererFrameEvent) => void;
14
26
  onBeforeEncode?: (event: {
15
27
  frame: number;
28
+ frameNumber: number;
29
+ frameId: string;
30
+ frameTimeMs?: number;
16
31
  timestamp: number;
17
32
  device: GPUDevice;
18
33
  context: GPUCanvasContext;
19
34
  encoder: GPUCommandEncoder;
20
35
  pass: GPURenderPassEncoder;
21
36
  canvas: HTMLCanvasElement;
37
+ xrActive: boolean;
22
38
  }) => void;
23
39
  onAfterSubmit?: (event: {
24
40
  frame: number;
41
+ frameNumber: number;
42
+ frameId: string;
43
+ frameTimeMs?: number;
25
44
  timestamp: number;
26
45
  device: GPUDevice;
27
46
  context: GPUCanvasContext;
28
47
  canvas: HTMLCanvasElement;
48
+ xrActive: boolean;
29
49
  }) => void;
50
+ onFrameComplete?: (event: RendererFrameEvent) => void;
30
51
  }
31
52
 
32
53
  export interface CreateGpuRendererOptions extends RendererHooks {
@@ -39,6 +60,12 @@ export interface CreateGpuRendererOptions extends RendererHooks {
39
60
  clearColor?: RendererColor;
40
61
  requestAnimationFrame?: (cb: FrameRequestCallback) => number;
41
62
  cancelAnimationFrame?: (id: number) => void;
63
+ frameIdFactory?: (event: {
64
+ frame: number;
65
+ timestamp: number;
66
+ canvas: HTMLCanvasElement;
67
+ xrActive: boolean;
68
+ }) => string;
42
69
  }
43
70
 
44
71
  export interface GpuRenderer {
@@ -46,7 +73,12 @@ export interface GpuRenderer {
46
73
  context: GPUCanvasContext;
47
74
  device: GPUDevice;
48
75
  format: GPUTextureFormat | string;
49
- renderOnce(timestamp?: number): { frame: number; timestamp: number };
76
+ renderOnce(timestamp?: number): {
77
+ frame: number;
78
+ frameId: string;
79
+ frameTimeMs?: number;
80
+ timestamp: number;
81
+ };
50
82
  start(): boolean;
51
83
  stop(): boolean;
52
84
  resize(cssWidth: number, cssHeight: number, devicePixelRatio?: number): {
@@ -74,6 +106,31 @@ export function supportsWebGpu(options?: { navigator?: Navigator | { gpu?: GPU }
74
106
 
75
107
  export function createGpuRenderer(options?: CreateGpuRendererOptions): Promise<GpuRenderer>;
76
108
 
109
+ export interface RendererDebugHooksOptions {
110
+ debugSession: {
111
+ recordFrame(sample: {
112
+ frameId?: string;
113
+ frameTimeMs: number;
114
+ targetFrameTimeMs?: number;
115
+ dropped?: boolean;
116
+ }): boolean;
117
+ };
118
+ targetFrameTimeMs?: number;
119
+ targetFrameRate?: number;
120
+ getTargetFrameTimeMs?: (event: RendererFrameEvent) => number | undefined;
121
+ onFrameStart?: (event: RendererFrameEvent & { owner: "renderer" }) => void;
122
+ onFrameComplete?: (
123
+ event: RendererFrameEvent & {
124
+ owner: "renderer";
125
+ targetFrameTimeMs?: number;
126
+ }
127
+ ) => void;
128
+ }
129
+
130
+ export function createRendererDebugHooks(
131
+ options: RendererDebugHooksOptions
132
+ ): Pick<RendererHooks, "onFrameStart" | "onFrameComplete">;
133
+
77
134
  export function bindRendererToXrManager(
78
135
  renderer: Pick<GpuRenderer, "setXrActive">,
79
136
  xrManager: {
@@ -87,4 +144,185 @@ export function bindRendererToXrManager(
87
144
  }
88
145
  ): () => void;
89
146
 
147
+ export type RendererWorkerProfileName = "realtime" | "xr";
148
+ export type RendererRepresentationBand = "near" | "mid" | "far" | "horizon";
149
+ export type RendererAccelerationStructureUpdateClass =
150
+ | "static"
151
+ | "rigid-dynamic"
152
+ | "deforming"
153
+ | "proxy";
154
+
155
+ export interface RendererInputBoundary {
156
+ readonly type: "stable-visual-snapshot";
157
+ readonly owner: typeof rendererDebugOwner;
158
+ readonly profile: RendererWorkerProfileName;
159
+ readonly authority: "visual";
160
+ readonly source: "scene-preparation";
161
+ readonly stable: true;
162
+ }
163
+
164
+ export interface RendererRenderStage {
165
+ readonly key:
166
+ | "primaryVisibility"
167
+ | "shadowAssist"
168
+ | "opaqueFoundation"
169
+ | "rtDirectLighting"
170
+ | "rtReflections"
171
+ | "rtGlobalIllumination"
172
+ | "denoiseTemporal"
173
+ | "transparents"
174
+ | "composition"
175
+ | "present";
176
+ readonly order: number;
177
+ readonly required: true;
178
+ readonly description: string;
179
+ readonly profile: RendererWorkerProfileName;
180
+ readonly workerJobKeys: readonly string[];
181
+ }
182
+
183
+ export interface RendererRepresentationPolicy {
184
+ readonly band: RendererRepresentationBand;
185
+ readonly profile: RendererWorkerProfileName;
186
+ readonly rasterMode:
187
+ | "full-live"
188
+ | "simplified-live"
189
+ | "proxy-or-cached"
190
+ | "horizon-shell";
191
+ readonly rtParticipation: "premium" | "selective" | "proxy" | "disabled";
192
+ readonly shadowSource:
193
+ | "ray-traced-primary"
194
+ | "regional-raster-and-proxy"
195
+ | "merged-proxy-casters"
196
+ | "baked-impression";
197
+ readonly temporalReuse: "balanced" | "aggressive" | "high" | "cached";
198
+ readonly updateCadenceDivisor: number;
199
+ }
200
+
201
+ export interface RendererAccelerationStructureUpdatePolicy {
202
+ readonly updateClass: RendererAccelerationStructureUpdateClass;
203
+ readonly description: string;
204
+ readonly profile: RendererWorkerProfileName;
205
+ }
206
+
207
+ export interface RendererWorkerBudgetLevelConfig {
208
+ maxDispatchesPerFrame: number;
209
+ maxJobsPerDispatch: number;
210
+ cadenceDivisor: number;
211
+ workgroupScale: number;
212
+ maxQueueDepth: number;
213
+ metadata: Readonly<{
214
+ owner: typeof rendererDebugOwner;
215
+ queueClass: typeof rendererWorkerQueueClass;
216
+ jobType: string;
217
+ quality: string;
218
+ }>;
219
+ }
220
+
221
+ export interface RendererWorkerBudgetLevel {
222
+ id: string;
223
+ estimatedCostMs: number;
224
+ config: RendererWorkerBudgetLevelConfig;
225
+ }
226
+
227
+ export interface RendererWorkerProfile {
228
+ readonly name: RendererWorkerProfileName;
229
+ readonly description: string;
230
+ readonly jobs: readonly string[];
231
+ }
232
+
233
+ export interface RendererWorkerManifestJob {
234
+ readonly key: string;
235
+ readonly label: string;
236
+ readonly worker: Readonly<{
237
+ jobType: string;
238
+ queueClass: typeof rendererWorkerQueueClass;
239
+ priority: number;
240
+ dependencies: readonly string[];
241
+ schedulerMode: "dag";
242
+ }>;
243
+ readonly performance: Readonly<{
244
+ id: string;
245
+ jobType: string;
246
+ queueClass: typeof rendererWorkerQueueClass;
247
+ domain: "resolution" | "geometry" | "post-processing" | "xr";
248
+ authority: "visual";
249
+ importance: "high" | "critical";
250
+ levels: readonly RendererWorkerBudgetLevel[];
251
+ }>;
252
+ readonly debug: Readonly<{
253
+ owner: typeof rendererDebugOwner;
254
+ queueClass: typeof rendererWorkerQueueClass;
255
+ jobType: string;
256
+ tags: readonly string[];
257
+ suggestedAllocationIds: readonly string[];
258
+ }>;
259
+ }
260
+
261
+ export interface RendererWorkerManifest {
262
+ readonly schemaVersion: 1;
263
+ readonly owner: typeof rendererDebugOwner;
264
+ readonly profile: RendererWorkerProfileName;
265
+ readonly description: string;
266
+ readonly queueClass: typeof rendererWorkerQueueClass;
267
+ readonly schedulerMode: "dag";
268
+ readonly inputBoundary: RendererInputBoundary;
269
+ readonly renderStages: readonly RendererRenderStage[];
270
+ readonly representationBands: readonly RendererRepresentationPolicy[];
271
+ readonly accelerationStructureUpdates: readonly RendererAccelerationStructureUpdatePolicy[];
272
+ readonly suggestedAllocationIds: readonly string[];
273
+ readonly jobs: readonly RendererWorkerManifestJob[];
274
+ }
275
+
276
+ export interface RayTracingRenderPlan {
277
+ readonly schemaVersion: 1;
278
+ readonly owner: typeof rendererDebugOwner;
279
+ readonly profile: RendererWorkerProfileName;
280
+ readonly inputBoundary: RendererInputBoundary & {
281
+ readonly snapshotId: string;
282
+ };
283
+ readonly renderStages: readonly RendererRenderStage[];
284
+ readonly representationBands: readonly (
285
+ | RendererRepresentationPolicy
286
+ | {
287
+ readonly band: RendererRepresentationBand;
288
+ }
289
+ )[];
290
+ readonly accelerationStructureUpdates: readonly RendererAccelerationStructureUpdatePolicy[];
291
+ readonly workerManifest: RendererWorkerManifest;
292
+ }
293
+
294
+ export function getRendererWorkerProfile(
295
+ name?: RendererWorkerProfileName
296
+ ): RendererWorkerProfile;
297
+
298
+ export function getRendererWorkerManifest(
299
+ name?: RendererWorkerProfileName
300
+ ): RendererWorkerManifest;
301
+
302
+ export function createRayTracingRenderPlan(options: {
303
+ snapshotId: string;
304
+ profile?: RendererWorkerProfileName;
305
+ representations?: readonly (
306
+ | RendererRepresentationPolicy
307
+ | {
308
+ readonly band: RendererRepresentationBand;
309
+ readonly [key: string]: unknown;
310
+ }
311
+ )[];
312
+ }): RayTracingRenderPlan;
313
+
314
+ export const rendererRepresentationBands: readonly RendererRepresentationBand[];
315
+ export const rendererAccelerationStructureUpdateClasses: readonly RendererAccelerationStructureUpdateClass[];
316
+ export const rendererRayTracingStageOrder: readonly RendererRenderStage["key"][];
317
+
90
318
  export const defaultRendererClearColor: readonly [number, number, number, number];
319
+ export const rendererDebugOwner: "renderer";
320
+ export const rendererWorkerQueueClass: "render";
321
+ export const defaultRendererWorkerProfile: "realtime";
322
+ export const rendererWorkerProfileNames: readonly RendererWorkerProfileName[];
323
+ export const rendererWorkerProfiles: Readonly<
324
+ Record<RendererWorkerProfileName, RendererWorkerProfile>
325
+ >;
326
+ export const rendererWorkerManifests: Readonly<
327
+ Record<RendererWorkerProfileName, RendererWorkerManifest>
328
+ >;