Skip to content

feat: WebGL shreds chart#373

Merged
asuzuki-jumptrading merged 1 commit into
mainfrom
asuzuki/shreds-overview
Jul 6, 2026
Merged

feat: WebGL shreds chart#373
asuzuki-jumptrading merged 1 commit into
mainfrom
asuzuki/shreds-overview

Conversation

@asuzuki-jumptrading

Copy link
Copy Markdown
Collaborator

No description provided.

* "now" is adjusted using an avg diff of server time and real now ts to smooth out server msg delays.
* We also delay "now" by one data update interval to prevent instability of right-most data.
*/
export function getAdjustedNow(serverTimeMs: number, prevTimeDiffs: number[]) {

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

moved from shreds progression plugin

* Get slots in draw order
* and max shreds count per slot for scaling
*/
export function getDrawInfo(

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

moved from shreds progression plugin

};
};

type XRange = {

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

moved to utils.ts for reuse

@asuzuki-jumptrading
asuzuki-jumptrading marked this pull request as ready for review June 30, 2026 18:26
@greptile-jt

greptile-jt Bot commented Jun 30, 2026

Copy link
Copy Markdown
Prompt To Fix All With AI
This is a comment left during a code review.
Path: src/features/Overview/ShredsProgression/WebGl/Chart.tsx
Line: 80-104

Comment:
**Missing WebGL resource cleanup on unmount**

The `THREE.WebGLRenderer` created in `setUpRenderer` (stored in `rendererRef`) is never disposed when the component unmounts. WebGL contexts are a limited browser resource (typically 8–16 per page), and each renderer also holds GPU memory for textures, buffers, and the scene graph (meshes, geometries, materials).

When this component unmounts and remounts (e.g. navigation), a new renderer is created but the old one's context and GPU allocations are leaked. Over time this can exhaust the browser's context limit, causing subsequent `WebGLRenderer` creation to fail silently or throw.

Add a cleanup effect to dispose of the renderer and its resources:

```suggestion
  useRafLoop(function drawShredsLoop(time: number) {
    if (
      lastRedrawRef.current == null ||
      time - lastRedrawRef.current >= REDRAW_INTERVAL_MS
    ) {
      lastRedrawRef.current = time;
      if (!rendererRef.current) {
        const result = setUpRenderer(width, height);
        if (!result) return;
        rendererRef.current = result;
        containerRef.current?.replaceChildren(result.renderer.domElement);
      } else {
        draw(
          chartId,
          prevTimeDiffsRef,
          rendererRef.current,
          visibleTsRangeRef,
          labelsRef,
          scale,
          false,
          [0, width],
        );
      }
    }
  });

  // Dispose WebGL resources on unmount
  useLayoutEffect(() => {
    return () => {
      const obj = rendererRef.current;
      if (!obj) return;
      obj.renderer.dispose();
      for (const slotMesh of obj.meshes.values()) {
        slotMesh.mesh.geometry.dispose();
      }
      for (const slotMesh of obj.availableMeshes) {
        slotMesh.mesh.geometry.dispose();
      }
      rendererRef.current = undefined;
    };
  }, []);
```

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: src/features/Overview/ShredsProgression/WebGl/Chart.tsx
Line: 9

Comment:
**No-op empty type import**

This import doesn't import anything and has no side effects for type-only imports. It should be removed.

```suggestion
```

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: src/features/Overview/ShredsProgression/WebGl/chartUtils.ts
Line: 364

Comment:
**Leftover debug code**

This commented-out return statement appears to be leftover from development/debugging and should be removed.

```suggestion
```

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "feat: WebGL shreds chart" | Re-trigger Greptile

Comment thread src/features/Overview/ShredsProgression/WebGl/Chart.tsx
Comment thread src/features/Overview/ShredsProgression/WebGl/Chart.tsx Outdated
Comment thread src/features/Overview/ShredsProgression/WebGl/chartUtils.ts Outdated
@greptile-jt

greptile-jt Bot commented Jun 30, 2026

Copy link
Copy Markdown
Prompt To Fix All With AI
This is a comment left during a code review.
Path: src/features/Overview/ShredsProgression/webglUtils.ts
Line: 73-74

Comment:
**Missing `DynamicDrawUsage` on initial buffers**

`ensureCapacity` correctly sets `DynamicDrawUsage` on resized buffers (lines 116-117), but `createSlotMesh` creates the initial attributes with the default `StaticDrawUsage`. Since these buffers are updated every frame via `addRectangleToMesh` + `needsUpdate = true`, they should use `DynamicDrawUsage` from the start so the GPU driver can optimize for frequent updates.

```suggestion
  const rectAttr = new THREE.InstancedBufferAttribute(rectArray, 4);
  const colorAttr = new THREE.InstancedBufferAttribute(colorArray, 3);
  rectAttr.setUsage(THREE.DynamicDrawUsage);
  colorAttr.setUsage(THREE.DynamicDrawUsage);
```

How can I resolve this? If you propose a fix, please make it concise.

Reviews (2): Last reviewed commit: "feat: WebGL shreds chart" | Re-trigger Greptile

Comment thread src/features/Overview/ShredsProgression/webglUtils.ts
@greptile-jt

greptile-jt Bot commented Jun 30, 2026

Copy link
Copy Markdown

Reviews (3): Last reviewed commit: "chore: fixes" | Re-trigger Greptile

@greptile-jt

greptile-jt Bot commented Jun 30, 2026

Copy link
Copy Markdown
Prompt To Fix All With AI
This is a comment left during a code review.
Path: src/features/Overview/ShredsProgression/atoms.ts
Line: 301-313

Comment:
**In-place Map mutation returns same reference**

`setMinDirtySlotByChartIfSmaller` and the corresponding `store.set` calls in `draw()` mutate the Map in-place and return the same object reference. This works today because all reads go through `store.get()` (imperative reads always see the latest value). However, Jotai v2 uses `Object.is` equality to suppress subscriber notifications — so if any component later subscribes to `minDirtySlotByChartAtom` via `useAtomValue`, it would never see updates since the reference never changes. Consider documenting this constraint or returning a new Map to make the pattern safe for future use.

How can I resolve this? If you propose a fix, please make it concise.

Reviews (4): Last reviewed commit: "fix: redraw skipped slots shreds" | Re-trigger Greptile

Comment thread src/features/Overview/ShredsProgression/atoms.ts
@greptile-jt

greptile-jt Bot commented Jun 30, 2026

Copy link
Copy Markdown

Reviews (5): Last reviewed commit: "chore: fix package.json, chunk for chart" | Re-trigger Greptile

@greptile-jt

greptile-jt Bot commented Jul 1, 2026

Copy link
Copy Markdown

Reviews (6): Last reviewed commit: "chore: max px ratio, check WebGL support" | Re-trigger Greptile

@asuzuki-jumptrading
asuzuki-jumptrading force-pushed the asuzuki/shreds-overview branch from cfddbc8 to 80976dc Compare July 6, 2026 17:41
@greptile-jt

greptile-jt Bot commented Jul 6, 2026

Copy link
Copy Markdown
Prompt To Fix All With AI
This is a comment left during a code review.
Path: src/features/Overview/ShredsProgression/WebGl/chartUtils.ts
Line: 247

Comment:
**`anythingDrawn` is always true after first frame**

After each draw, `minDirtySlotByChartAtom` is reset to `Infinity` (line 234). On the next frame, `minDirtySlot = Infinity`, and `Infinity != null` evaluates to `true`. This means `anythingDrawn` is always true once the chart initializes, so the dirty-slot render skip never triggers.

For a live chart this has no impact because `cameraChanged` is also true every frame (the visible time range shifts with `Date.now()`). But if pause/pan is added later (as the comment on line 84 suggests), this would cause unnecessary `renderer.render()` calls on every frame even when nothing changed.

```suggestion
  const anythingDrawn = minDirtySlot != null && isFinite(minDirtySlot);
```

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: src/features/Overview/ShredsProgression/webglSupport.ts
Line: 7-14

Comment:
**Probed WebGL2 context not released**

`canvas.getContext("webgl2")` creates a real WebGL2 context that occupies one of the browser's limited context slots (typically 8–16). The canvas is an orphan element so the context will eventually be GC'd, but it may linger until the GC runs. Since this probe runs once at startup it's unlikely to cause issues in practice, but explicitly releasing the context is cheap insurance — especially given the PR already has `forceContextLoss` cleanup on the renderer side.

```suggestion
export function isWebGl2Available(): boolean {
  try {
    const canvas = document.createElement("canvas");
    const ctx = canvas.getContext("webgl2");
    if (!ctx) return false;
    ctx.getExtension("WEBGL_lose_context")?.loseContext();
    return true;
  } catch {
    return false;
  }
}
```

How can I resolve this? If you propose a fix, please make it concise.

Reviews (7): Last reviewed commit: "chore: max px ratio, check WebGL support" | Re-trigger Greptile

Comment thread src/features/Overview/ShredsProgression/WebGl/chartUtils.ts Outdated
Comment thread src/features/Overview/ShredsProgression/webglSupport.ts
@greptile-jt

greptile-jt Bot commented Jul 6, 2026

Copy link
Copy Markdown

Reviews (8): Last reviewed commit: "fix: anythingDrawn check" | Re-trigger Greptile

Comment thread src/features/Overview/ShredsProgression/WebGl/chartUtils.ts Outdated
@greptile-jt

greptile-jt Bot commented Jul 6, 2026

Copy link
Copy Markdown

Reviews (9): Last reviewed commit: "fix: handle context loss and restore, up..." | Re-trigger Greptile

@asuzuki-jumptrading
asuzuki-jumptrading force-pushed the asuzuki/shreds-overview branch from 0f03f27 to c92de05 Compare July 6, 2026 22:16
@greptile-jt

greptile-jt Bot commented Jul 6, 2026

Copy link
Copy Markdown
Prompt To Fix All With AI
This is a comment left during a code review.
Path: src/features/Overview/ShredsProgression/WebGl/Chart.tsx
Line: 86-89

Comment:
**WebGL resources leaked on context restore**

`clearTimeout(contextLostTimeoutRef.current)` cancels the timer but does **not** set the ref to `undefined`. When `triggerRemount()` unmounts this component, the cleanup effect (line 105) evaluates `contextLostTimeoutRef.current != null``true` (it's still the old timeout ID number), so `isContextLost` is `true` and the entire GPU cleanup block (geometry disposal, `renderer.dispose()`, `forceContextLoss()`) is skipped.

After the context is restored the GL context is live again, so the old renderer holds a valid context that should be released. On repeated context-loss/restore cycles (e.g. repeated tab backgrounding) this will accumulate leaked WebGL contexts until the browser's limit (typically 8–16) is exhausted.

```suggestion
  const handleContextRestored = useCallback(() => {
    clearTimeout(contextLostTimeoutRef.current);
    contextLostTimeoutRef.current = undefined;
    triggerRemount();
  }, [triggerRemount]);
```

How can I resolve this? If you propose a fix, please make it concise.

Reviews (10): Last reviewed commit: "fix: handle context loss and restore, up..." | Re-trigger Greptile

Comment thread src/features/Overview/ShredsProgression/WebGl/Chart.tsx
@asuzuki-jumptrading
asuzuki-jumptrading force-pushed the asuzuki/shreds-overview branch from c92de05 to 8a05898 Compare July 6, 2026 22:23
@greptile-jt

greptile-jt Bot commented Jul 6, 2026

Copy link
Copy Markdown

Reviews (11): Last reviewed commit: "fix: handle context loss and restore, up..." | Re-trigger Greptile

@asuzuki-jumptrading
asuzuki-jumptrading force-pushed the asuzuki/shreds-overview branch from 8a05898 to b4fd4f4 Compare July 6, 2026 23:04
@greptile-jt

greptile-jt Bot commented Jul 6, 2026

Copy link
Copy Markdown

Reviews (12): Last reviewed commit: "feat: WebGL shreds chart" | Re-trigger Greptile

@asuzuki-jumptrading
asuzuki-jumptrading merged commit 44e837f into main Jul 6, 2026
2 checks passed
@asuzuki-jumptrading
asuzuki-jumptrading deleted the asuzuki/shreds-overview branch July 6, 2026 23:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants