ProtoPie renderer — renderer-wasm 개발 문서 원문 텍스트 추출본 / 2026-09-14 받는 사람 # renderer-wasm 브라우저 JavaScript 가 호출하는 wasm-bindgen entry. SceneGraph → frame render loop 의 외부 표면. ## Module layout ``` src/ ├── lib.rs # wasm entry + module export ├── renderer/ │ ├── mod.rs # WasmRenderer lifecycle (create, render, resize) │ ├── api_support.rs # JsValue error formatting, JSON parsing, label helpers │ ├── backend.rs # GraphPassBackendHandle (Execution/Control trait split) + TessGraphPassBackend │ ├── config.rs # runtime override API (curve variant, lowering preset, atlas heuristic, fonts, texture budget) │ ├── debug.rs # frame stats, runtime info, scene debug JSON, log drain │ ├── pass_encoder.rs # TessPassEncoder (impl GraphPassEncoder) │ ├── frame_context.rs # SceneRenderContext re-export │ ├── viewport/ # ViewportBuilder, ViewportResolution (surface clamping) │ └── errors.rs # FrameRenderError, FrameRecovery ├── media/source_resolver.rs # WasmTextureSourceResolver └── image/ ├── zero_copy.rs # WebGPU zero-copy provider └── readback.rs # Canvas readback provider ``` ## Public API (wasm-bindgen) | Method | Role | |---------------------------------------------|-----------------------------------------------------| | `WasmRenderer::create(canvas)` | GPU init + renderer 생성 (async) | | `apply_batch(json)` | CommandBatch JSON → SceneGraph | | `render_frame()` | dirty + camera invalidation 기반 1 frame | | `resize(w, h)` | surface / camera viewport | | `set_camera(x, y, zoom)` | 2D pan / zoom | | `set_camera_dpr(dpr)` | DPR 갱신 | | `reset_camera()` | 초기 카메라 | | `register_font_bytes(bytes)` | Slug text 용 런타임 폰트 등록 (host → wasm seam) | | `set_curve_encoding_variant(variant)` | Slug A/B/C/D / baseline 전환 (debug) | | `set_texture_budget(bytes)` | 텍스처 GPU 메모리 예산 | | `get_frame_stats()` | 마지막 프레임 통계 JSON (text diagnostics, line counts, clipped lines, glyph/decoration/text-stroke cache counters 포함) | | `drain_logs()` | log ring buffer (≤1000) → JSON 배열 | | `tess_render_graph_summary()` | 현재 프레임 RenderGraph 요약 | ## Frame route 1. 입력 dispatch: `apply_batch`, `set_camera*`, `resize`. 2. `render_frame()` 시작에서 `StrokePlanSet` 을 frame-local 로 한 번 compile. 3. `prepare_frame` invalidation 입력: - `force_redraw` - `scene.has_dirty_nodes()` - `scene.has_texture_binding_changes()` - `resource_manager.update_textures(...)` - `camera.revision() != last_camera_revision` 4. Texture binding 변경 시 `resource_manager.sync_texture_bindings_from_scene_with_strokes(scene, stroke_plans, resolver)`. 5. 리소스: `sync_display_sizes_with_strokes` → `advance_frame` → `update_textures`. 6. Graph: `RenderGraphBuilder::build_from_scene_with_viewport_and_strokes(...)`. - Stroke texture lookup 은 frame `StrokePlanSet` 의 `paint_slot` 을 사용. 7. Execute: `RenderGraphExecutor::execute(...)` + `TessPassEncoder` (impl `GraphPassEncoder`). - 미지원 pass kind → fallback `TessPainter::render_scene_to_view` (base fill). - surface 가 `TEXTURE_BINDING` 미지원 + graph 가 `CaptureBackdrop` / `CaptureSubtree` 포함 시 → fallback. - graph/fallback 모두 frame end 전에 `TessPainter::prune_persistent_caches(...)` 호출. 8. 폰트 등록 (`register_font_bytes`) 성공 시 `TessPainter::clear_text_cache()` + `force_redraw`. - Text layout / outline / positioned glyph/decoration/stroke curve cache 와 persistent glyph atlas 가 함께 비워져야 한다. 9. Frame end: `scene.clear_all_dirty()` + `last_camera_revision = camera.revision()`. ## Error / recovery | Symptom | Action | |------------------------------------------|---------------------------------------| | Surface `Lost` / `Outdated` | reconfigure + redraw | | Surface `Timeout` | retry soon | | Graph build / execute deterministic err | skip until next dirty event | | `Present` 미실행 | frame error | | Unsupported pass kind | fallback direct scene render | | Non-sampleable surface + capture graph | fallback direct scene render | ## Hard rules - 공개 함수는 `#[wasm_bindgen]`. JS 친화 타입만 외부 노출. - 에러는 `Result`. - `console_error_panic_hook` 초기화 필수. - Surface 생성: `wgpu::SurfaceTarget::Canvas(...)`. - 런타임 폰트 등록은 `register_font_bytes` 만. image / resource cache 와 분리. - Slug variant override 는 benchmark / debug seam. Baseline 기본값은 renderer-tess 소유. - wasm single-thread 경로에서는 `Arc` 공유 소유 유지. `clippy::arc_with_non_send_sync` 는 wasm entry 경계에서만 suppress. - `OffscreenCanvasRenderingContext2d::get_image_data()` 는 `web_sys_unstable_apis` 유무에 따라 시그니처 변경. `image/readback.rs` 가 cfg 분기로 양쪽 지원. ## Import 규칙 - `ResourceManager`, `TextureSourceResolver`, `PaintTextureProvider` 등은 `renderer_resource` 에서 직접 import. - `TessPainter` 는 `renderer_tess` 에서. - 그래프 타입은 `renderer_tess` re-export 경유 (원본: `renderer-graph`). ## Build ```bash cargo build --target wasm32-unknown-unknown --release -p renderer-wasm ``` 사람 사람 사람 참조 사람 숨은참조 사람 제목