Skip to content

Real-device WebGPU crash in directional shadow receiver path after Three shadow render completion #333

@tgabereal

Description

@tgabereal

Real-device WebGPU crash in directional shadow receiver path after Three shadow render completion

Summary

We reduced a WebGPU crash in our React Native / Expo app to a small repro that fails on both iOS simulator and a real iPhone, but only when a directional-light shadow receiver path is active.

What is already proven:

  • raw WebGPU passes on simulator and real device
  • raw Three WebGPU passes on simulator and real device
  • patched R3F WebGPU passes on simulator and real device
  • the reduced shadow receiver repro fails on simulator and real device
  • three completes the shadow render path on the JS side
  • the only local patch that materially changed the failure boundary was in react-native-wgpu
  • no safe local workaround is proven

Current best attribution:

  • this does not look like a generic WebGPU, generic Three, or generic R3F failure
  • this looks like a native/backend WebGPU failure on the react-native-wgpu / Dawn / Metal path during the shadow-pass submission lifecycle
  • our best current stage classification is: during_shadow_pass_submission_before_native_present_completion

Environment

  • react-native-wgpu: 0.5.8
  • react-native: 0.81.5
  • expo: ~54.0.0
  • react: 19.1.0
  • three: 0.183.2
  • @react-three/fiber: 9.5.0
  • real device used for confirmation: iPhone 16 Pro Max

Passing controls

These all pass on simulator and real device:

  • raw WebGPU
  • raw Three WebGPU
  • patched R3F WebGPU

Failing reduced repro

The failing repro is a reduced scene with a directional light and a shadow receiver.

Final narrowed failing condition:

  • receiveShadow = true
  • directionalShadow = true

This still fails across:

  • materials:
    • MeshStandardMaterial
    • MeshLambertMaterial
    • MeshBasicMaterial
  • geometries:
    • circle
    • plane
    • ring

So this is not just “standard material on a circle”.

Observed behavior

On a real iPhone:

  • the reduced repro reaches route-ready
  • the process is gone by the end of the probe window
  • deeper native trace capture could not be flushed before failure from this environment

On simulator:

  • the same reduced repro also fails

Important local findings

1. three is not the first failing layer anymore

Our engine-level source-debugging narrowed the boundary further:

  • three reaches/completes the shadow render path on the JS/engine side
  • the remaining blocker appears after that, in the native/backend path

2. A react-native-wgpu patch was the only patch that materially changed the failure boundary

We tested several local patch candidates.

Only one materially changed behavior:

  • a native present/backend guard in react-native-wgpu

That candidate:

  • made the reduced repro pass on simulator
  • made broader Doorway validation scenes pass on simulator and real device
  • but the reduced shadow repro still failed on real device in the clean confirmation rerun

This is why react-native-wgpu is now our primary issue target.

3. Warm-up / delayed shadow enable did not solve it

We also tested delayed shadow enable / warm-up gating.

Result:

  • no usable effect on real device
  • the reduced repro still failed before the gate meaningfully activated

Why we think this belongs here

At this point the evidence suggests:

  • the reduced repro is valid
  • generic WebGPU and generic Three/R3F are fine
  • the failure is in the native/backend path specific to the shadow-pass lifecycle on this stack
  • the only patch that moved the boundary at all was in react-native-wgpu

That makes react-native-wgpu the primary owner to inspect next.

Primary ask

Can you advise where to inspect next in the native/backend path for this reduced real-device shadow-pass failure?

The most relevant current question is:

  • why does the reduced directional-shadow receiver repro still die on real device after three shadow render completion, even though a native/backend guard is enough to make broader validation surfaces pass?

If there is a specific Dawn / Metal / react-native-wgpu texture, render-pass, queue-submit, or present-adjacent path that matches this pattern, that is the highest-value direction for us.

If helpful, I can provide:

  • the reduced repro surface
  • machine-readable simulator vs real-device comparison outputs
  • the exact local patch candidates we tested

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions