@@ -4,6 +4,7 @@ import React, {
44 useContext ,
55 useEffect ,
66 useMemo ,
7+ useRef ,
78 useState ,
89} from 'react' ;
910import tgpu , { type TgpuRoot } from 'typegpu' ;
@@ -58,6 +59,7 @@ type RootContextResult =
5859 | { status : 'rejected' ; error : unknown } ;
5960
6061interface RootContext {
62+ readonly rootRequested : boolean ;
6163 initOrGetRoot ( ) : RootContextResult ;
6264}
6365
@@ -71,6 +73,10 @@ class OwnRootContext implements RootContext {
7173 promise : tgpu . init ( ) . then (
7274 ( root ) => {
7375 this . #result = { status : 'resolved' , value : root } ;
76+ root . device . lost . then ( ( ) => {
77+ // TODO: React to reason
78+ this . #result = undefined ;
79+ } ) ;
7480 return root ;
7581 } ,
7682 ( error ) => {
@@ -83,6 +89,10 @@ class OwnRootContext implements RootContext {
8389
8490 return this . #result;
8591 }
92+
93+ get rootRequested ( ) {
94+ return this . #result !== undefined ;
95+ }
8696}
8797
8898class ExistingRootContext implements RootContext {
@@ -95,6 +105,10 @@ class ExistingRootContext implements RootContext {
95105 initOrGetRoot ( ) : RootContextResult {
96106 return this . result ;
97107 }
108+
109+ get rootRequested ( ) {
110+ return this . result !== undefined ;
111+ }
98112}
99113
100114/**
@@ -144,7 +158,32 @@ export function useRoot(): TgpuRoot {
144158 if ( result . status === 'rejected' ) {
145159 throw result . error as Error ;
146160 }
147- return result . status === 'pending' ? use ( result . promise ) : result . value ;
161+ const root = result . status === 'pending' ? use ( result . promise ) : result . value ;
162+
163+ // NOTE: Useful docs: https://toji.dev/webgpu-best-practices/device-loss.html
164+ const [ _ , rerender ] = useState ( 0 ) ;
165+ const lostRootsRef = useRef < WeakSet < TgpuRoot > > ( new WeakSet ( ) ) ;
166+ useEffect ( ( ) => {
167+ let cancelled = false ;
168+
169+ root . device . lost . then ( ( ) => {
170+ // TODO: React to reason
171+ if ( cancelled || lostRootsRef . current . has ( root ) ) {
172+ return ;
173+ }
174+ lostRootsRef . current . add ( root ) ;
175+
176+ if ( ! context . rootRequested ) {
177+ rerender ( ( a ) => a + 1 ) ;
178+ }
179+ } ) ;
180+
181+ return ( ) => {
182+ cancelled = true ;
183+ } ;
184+ } , [ root ] ) ;
185+
186+ return root ;
148187}
149188
150189/**
0 commit comments