Skip to content

[Bug] macOS Tauri WebGL context loss in fers-ui #181

@davidbits

Description

@davidbits

Summary

Running the UI in Tauri on macOS results in the 3D scenario view failing to render. The Tauri webview console reports an immediate WebGL context loss during THREE.WebGLRenderer initialization, followed by a React Three Fiber failure when it attempts to inspect shader precision on a null/invalid gl object. The same UI is expected to work on both macOS and Linux.

Affected Areas

  • packages/fers-ui/src/views/ScenarioView.tsx
  • packages/fers-ui/src/components/WorldView.tsx
  • packages/fers-ui/src/components/CameraManager.tsx
  • packages/fers-ui/src/components/ScaleManager.tsx
  • packages/fers-ui/src/main.tsx
  • packages/fers-ui/src-tauri/tauri.conf.json
  • packages/fers-ui/src-tauri/capabilities/default.json

Environment

  • Platform: macOS
  • Runtime: Tauri dev mode via bun ui:dev
  • Frontend stack:
    • React 19
    • @react-three/fiber 9.5.0
    • three 0.183.2
    • @react-three/drei 10.7.7
  • Expected compatibility target: macOS and Linux

Reproduction Steps

  1. Start the application in dev mode on macOS with bun ui:dev.
  2. Open the Scenario view.
  3. Observe that the 3D viewport remains blank.
  4. Inspect the Tauri webview console and terminal output.

Actual Result

  • The 3D viewport is blank.
  • WebGL context creation or early renderer startup fails.
  • React Three Fiber throws during root.current.configure(...) because the GL context object is null or unusable.

Expected Result

  • The 3D viewport should render correctly in Tauri on macOS.
  • The same codepath should continue to work on Linux.

Observed Logs

Tauri console

[Debug] [vite] connecting...
[Debug] [vite] connected.
[Warning] THREE.THREE.Clock: This module has been deprecated. Please use THREE.Timer instead.
[Error] WebGL: context lost.
[Error] Unhandled Promise Rejection: TypeError: null is not an object (evaluating 'gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.HIGH_FLOAT).precision')
[Log] THREE.WebGLRenderer: Context Lost.
[Log] Scenario imported and synchronized successfully from: "/Users/davidyoung/CLionProjects/FERS/cw.fersxml"
[Log] Successfully synced state to backend.
[Error] Unhandled Promise Rejection: TypeError: null is not an object (evaluating 'gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.HIGH_FLOAT).precision')

macOS terminal output

RemoteLayerTreeDrawingAreaProxyMac::scheduleDisplayLink(): page has no displayID
RemoteLayerTreeDrawingAreaProxyMac::scheduleDisplayLink(): page has no displayID

Failure Point

The failure appears during renderer setup inside Three.js / React Three Fiber.

Three.js context creation path

The reported failure occurs when THREE.WebGLRenderer attempts to create a webgl2 context:

_gl = getContext(contextName, contextAttributes);

This is where the context loss is observed.

React Three Fiber configuration path

React Three Fiber later attempts to configure the root and reads shader precision from gl:

await root.current.configure({ ... })

This eventually fails with:

gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.HIGH_FLOAT).precision;

At that point gl is null or otherwise invalid because the WebGL context has already been lost.

Current Scene Characteristics Relevant to the Bug

The scenario view currently initializes a React Three Fiber Canvas with a large far plane and a non-trivial scene graph:

  • packages/fers-ui/src/views/ScenarioView.tsx
    • Renders the top-level <Canvas> for the 3D scene
    • Uses a camera with far: 1e8
  • packages/fers-ui/src/components/WorldView.tsx
    • Adds MapControls
    • Adds ambient and directional lights
    • Loads an HDR environment map with <Environment files="/potsdamer_platz_1k.hdr" />
    • Renders platforms, motion paths, boresights, antenna patterns, labels, and link visualization
  • packages/fers-ui/src/components/ScaleManager.tsx
    • Reads gl.domElement.clientHeight every frame
  • packages/fers-ui/src/components/CameraManager.tsx
    • Uses useThree() and per-frame camera/control updates

Although the crash occurs before meaningful rendering begins, these features may still matter because some of them influence the renderer configuration, resource allocation, or first-frame setup.

What Was Tried

The following mitigations were attempted locally but did not resolve the issue:

  1. Custom renderer/context creation path in ScenarioView with explicit webgl2 -> webgl -> experimental-webgl fallback.
  2. Disabling logarithmicDepthBuffer on macOS WebKit while keeping it enabled elsewhere.
  3. Replacing the custom renderer path with a more conservative Canvas gl configuration:
    • antialias: false
    • stencil: false
    • logarithmicDepthBuffer: false
    • powerPreference: 'default'
    • dpr={1}
    • frameloop="always"
  4. Removing React.StrictMode from packages/fers-ui/src/main.tsx to avoid double initialization in dev.
  5. Disabling the HDR environment map on macOS WebKit.

Despite these changes, the Tauri console continued to report the same context-loss and null-gl errors, and the 3D view remained blank.

Likely Scope of the Problem

This looks less like a normal scene-level rendering bug and more like a macOS Tauri/WebKit WebGL initialization problem or compatibility issue triggered very early in renderer startup.

Possible categories:

  • WebKit-specific WebGL/WebGL2 failure inside the Tauri webview on macOS
  • Tauri window/display initialization issue on macOS, suggested by:
RemoteLayerTreeDrawingAreaProxyMac::scheduleDisplayLink(): page has no displayID
  • A React Three Fiber / Three.js initialization path that assumes a valid GL object after context creation and does not recover when the context is lost immediately
  • A renderer capability query happening after a failed or lost context, causing the getShaderPrecisionFormat crash

Impact

  • macOS users cannot use the 3D Scenario view in Tauri dev mode
  • Core scene editing/inspection workflow is blocked on macOS
  • Linux compatibility must be preserved, so any fix needs to remain cross-platform

Suggested Next Investigation

  1. Confirm whether the issue reproduces in a minimal Tauri + React Three Fiber + Three.js scene on the same macOS machine.
  2. Determine whether Tauri on macOS is using WebKit WebGL2 successfully at all, or whether only WebGL1 is available/stable.
  3. Add temporary runtime diagnostics for:
    • whether canvas.getContext('webgl2') succeeds
    • whether canvas.getContext('webgl') succeeds
    • renderer capabilities after creation
    • webglcontextlost / webglcontextrestored event timing
  4. Check whether the issue occurs only in dev mode or also in a packaged build.
  5. Check Tauri/macOS/WebKit known issues related to displayID, display link scheduling, or WebGL context loss.
  6. Reduce the scene to the smallest possible Canvas with no environment map, no controls, and one mesh to identify whether the failure is:
    • pure context creation
    • first render
    • PMREM/environment processing
    • control/event hookup

Validation Status

  • bun run lint passes in packages/fers-ui
  • bun run build passes in packages/fers-ui
  • Runtime issue on macOS remains unresolved

Notes

  • This report captures the current state after unsuccessful remediation attempts so the next investigation can start from observed facts rather than retrying the same mitigations.

Metadata

Metadata

Assignees

Labels

priorityMust be addressed with high priority.scope: uiRelated to the Tauri/React UI (fers-ui).type: bugSomething isn't working as expected.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions