-
Notifications
You must be signed in to change notification settings - Fork 2.4k
feat(viewer): ?disable=draw — skip scene rendering for graph-only consumers #482
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,6 @@ | ||
| import { useFrame, useThree } from '@react-three/fiber' | ||
| import { useCallback, useEffect, useMemo, useRef, useState } from 'react' | ||
| import { Color, Layers, type Object3D, UnsignedByteType } from 'three' | ||
| import { Color, Layers, type Object3D, Scene, UnsignedByteType } from 'three' | ||
| import { ssgi } from 'three/addons/tsl/display/SSGINode.js' | ||
| import { denoise } from 'three/examples/jsm/tsl/display/DenoiseNode.js' | ||
| import { | ||
|
|
@@ -57,6 +57,11 @@ export const SSGI_PARAMS = { | |
| // - outline: skip the merged-outline node and its 14 internal RTs | ||
| // - postFx: bypass the whole RenderPipeline and use renderer.render(scene, camera) | ||
| // directly — isolates raw scene-render cost from any post-FX overhead | ||
| // - draw: skip the render call entirely — frames still tick (useFrame | ||
| // systems, scene-ready) but no draw is ever submitted. For | ||
| // consumers that only need the built scene graph, never pixels: | ||
| // the headless bake worker renders on SwiftShader (CPU), where | ||
| // per-frame vertex/draw cost dominates the whole capture. | ||
| function readPerfDisableFlags() { | ||
| if (typeof window === 'undefined') { | ||
| return { ao: false, denoise: false, outline: false, postFx: false } | ||
|
|
@@ -84,6 +89,17 @@ const PERF_POST_FX_DISABLED = | |
| .map((s) => s.trim()), | ||
| ).has('postFx') | ||
|
|
||
| const PERF_DRAW_DISABLED = | ||
| typeof window !== 'undefined' && | ||
| new Set( | ||
| (new URLSearchParams(window.location.search).get('disable') ?? '') | ||
| .split(',') | ||
| .map((s) => s.trim()), | ||
| ).has('draw') | ||
|
|
||
| // Stand-in scene for `?disable=draw` frames — cleared, never populated. | ||
| const emptyScene = new Scene() | ||
|
|
||
| const MAX_PIPELINE_RETRIES = 3 | ||
| const RETRY_DELAY_MS = 500 | ||
|
|
||
|
|
@@ -562,6 +578,23 @@ const PostProcessingPasses = ({ | |
| return | ||
| } | ||
|
|
||
| // `?disable=draw`: nothing downstream wants pixels — render an EMPTY scene | ||
| // instead of the real one. This is the only render call (positive-priority | ||
| // useFrame subscribers already disable R3F's automatic render), so the real | ||
| // scene is never drawn: per-frame vertex/draw cost drops to a single 64×64 | ||
| // clear, which is what makes headless bakes viable on SwiftShader (CPU). | ||
| // Rendering nothing at all is NOT an option — with zero submitted frames | ||
| // Chromium's no-damage scheduler throttles rAF to 1Hz (measured), stalling | ||
| // the useFrame systems the bake still needs. | ||
| if (PERF_DRAW_DISABLED) { | ||
| try { | ||
| ;(renderer as any).render(emptyScene, camera) | ||
| } catch { | ||
| // A failed empty draw changes nothing — systems keep ticking. | ||
| } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Swallowed empty draw failuresMedium Severity The Reviewed by Cursor Bugbot for commit e339147. Configure here. |
||
| return | ||
| } | ||
|
|
||
| // Animate background colour toward the current scene theme target (same lerp as AnimatedBackground) | ||
| bgTarget.current.set(getSceneTheme(useViewer.getState().sceneTheme).background) | ||
| bgCurrent.current.lerp(bgTarget.current, Math.min(delta, 0.1) * 4) | ||
|
|
||


There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Draw flag skips pipeline guard
Medium Severity
When
?disable=drawis active, the post-processing pipeline'suseEffectstill builds and allocates the full WebGPURenderPipeline. This creates unnecessary memory overhead and can slow startup for headless bakes, since theuseFrameloop then bypasses this unused pipeline.Reviewed by Cursor Bugbot for commit e339147. Configure here.