@@ -33,6 +33,8 @@ import {
3333 canvasElAtom ,
3434 canvasParentElAtom ,
3535 wgpuAvailabilityAtom ,
36+ wgpuContextAtom ,
37+ wgpuDeviceAtom ,
3638 wgputoyPreludeAtom
3739} from 'lib/atoms/wgputoyatoms' ;
3840import { ComputeEngine } from 'lib/engine' ;
@@ -94,11 +96,12 @@ const WgpuToyController = props => {
9496 const setEntryPoints = useSetAtom ( entryPointsAtom ) ;
9597 const setEntryTimers = useSetAtom ( entryTimersAtom ) ;
9698 const setSaveColorTransitionSignal = useSetAtom ( saveColorTransitionSignalAtom ) ;
99+ const setPrelude = useSetAtom ( wgputoyPreludeAtom ) ;
97100
98101 const canvas = useAtomValue ( canvasElAtom ) ;
99- const setPrelude = useSetAtom ( wgputoyPreludeAtom ) ;
100102 const wgpuAvailability = useAtomValue ( wgpuAvailabilityAtom ) ;
101-
103+ const wgpuContext = useAtomValue ( wgpuContextAtom ) ;
104+ const wgpuDevice = useAtomValue ( wgpuDeviceAtom ) ;
102105 const parentRef = useAtomValue < HTMLElement | null > ( canvasParentElAtom ) ;
103106
104107 const [ width , setWidth ] = useTransientAtom ( widthAtom ) ;
@@ -170,51 +173,69 @@ const WgpuToyController = props => {
170173 where manualReload gets set before the controller is loaded, which
171174 results in the effect hook for manualReload never getting called.
172175 */
173- useAnimationFrame ( async e => {
176+ useAnimationFrame ( e => {
174177 if ( sliderUpdateSignal ( ) && ! needsInitialReset ( ) ) {
175- await updateUniforms ( ) ;
178+ ( async ( ) => {
179+ await updateUniforms ( ) ;
180+ } ) ( ) ;
176181 }
177182 if ( performingInitialReset ( ) ) {
178183 // wait for initial reset to complete
179- } else if ( needsInitialReset ( ) && dbLoaded ( ) ) {
180- console . log ( 'Initialising engine...' ) ;
181- setPerformingInitialReset ( true ) ;
182- await ComputeEngine . create ( ) ;
183- const engine = ComputeEngine . getInstance ( ) ;
184- if ( ! canvas ) {
185- console . error ( 'Canvas not found' ) ;
186- return ;
187- }
188- engine . setSurface ( canvas ) ;
189- engine . onSuccess ( handleSuccess ) ;
190- engine . onUpdate ( handleUpdate ) ;
191- engine . onError ( handleError ) ;
192- setTimer ( 0 ) ;
193- engine . setPassF32 ( float32Enabled ) ;
194- setProfilerEnabled ( false ) ;
195- updateResolution ( ) ;
196- engine . resize ( width ( ) , height ( ) ) ;
197- engine . reset ( ) ;
198- await loadTexture ( 0 , loadedTextures [ 0 ] . img ) ;
199- await loadTexture ( 1 , loadedTextures [ 1 ] . img ) ;
200- await updateUniforms ( ) ;
201- console . log ( 'Compiling shader...' ) ;
202- const source = await processShaderCode ( engine ) ;
203- if ( ! source ) {
204- console . error ( 'Initialisation aborted: shader compilation failed' ) ;
205- return ;
206- }
207- await engine . compile ( source ) ;
208- setPrelude ( engine . getPrelude ( ) ) ;
209- engine . render ( ) ;
210- setManualReload ( false ) ;
211- setNeedsInitialReset ( false ) ;
212- setPerformingInitialReset ( false ) ;
213- console . log ( 'Initialisation complete' ) ;
184+ } else if ( needsInitialReset ( ) && dbLoaded ( ) && wgpuContext && wgpuDevice ) {
185+ ( async ( ) => {
186+ console . log ( 'Initialising engine...' ) ;
187+
188+ try {
189+ const engineCreationPromise = ComputeEngine . create ( wgpuContext , wgpuDevice ) ;
190+ const textureLoadingPromises = [
191+ loadTexture ( 0 , loadedTextures [ 0 ] . img ) ,
192+ loadTexture ( 1 , loadedTextures [ 1 ] . img )
193+ ] ;
194+
195+ await engineCreationPromise ;
196+ setPerformingInitialReset ( true ) ;
197+
198+ const engine = ComputeEngine . getInstance ( ) ;
199+ engine . onSuccess ( handleSuccess ) ;
200+ engine . onUpdate ( handleUpdate ) ;
201+ engine . onError ( handleError ) ;
202+
203+ setTimer ( 0 ) ;
204+ engine . setPassF32 ( float32Enabled ) ;
205+ setProfilerEnabled ( false ) ;
206+ updateResolution ( ) ;
207+ engine . resize ( width ( ) , height ( ) ) ;
208+ engine . reset ( ) ;
209+
210+ console . log ( 'Waiting for texture loading...' ) ;
211+ await Promise . all ( textureLoadingPromises ) ;
212+
213+ await updateUniforms ( ) ;
214+ console . log ( 'Compiling shader...' ) ;
215+ const source = await processShaderCode ( engine ) ;
216+
217+ if ( ! source ) {
218+ console . error ( 'Initialisation aborted: shader compilation failed' ) ;
219+ return ;
220+ }
221+
222+ await engine . compile ( source ) ;
223+ setPrelude ( engine . getPrelude ( ) ) ;
224+ engine . render ( ) ;
225+
226+ setManualReload ( false ) ;
227+ setNeedsInitialReset ( false ) ;
228+ setPerformingInitialReset ( false ) ;
229+ console . log ( 'Initialisation complete' ) ;
230+ } catch ( error ) {
231+ console . error ( 'Initialization failed:' , error ) ;
232+ setPerformingInitialReset ( false ) ;
233+ }
234+ } ) ( ) ;
214235 } else if ( dbLoaded ( ) && manualReload ( ) ) {
215236 console . log ( 'Manual reload triggered' ) ;
216237 setManualReload ( false ) ;
217- await recompile ( ) ;
238+ recompile ( ) ;
218239 }
219240 if ( needsInitialReset ( ) ) {
220241 return ;
@@ -323,14 +344,15 @@ const WgpuToyController = props => {
323344 } , [ ] ) ;
324345
325346 const requestFullscreen = useCallback ( ( ) => {
326- if ( canvas && ! document . fullscreenElement ) {
327- canvas . requestFullscreen ( { navigationUI : 'hide' } ) ;
347+ try {
348+ if ( canvas && ! document . fullscreenElement ) {
349+ canvas . requestFullscreen ( { navigationUI : 'hide' } ) ;
350+ }
351+ } catch {
352+ console . error ( 'Error requesting fullscreen' ) ;
328353 }
329354 } , [ ] ) ;
330355
331- // init effect
332- useEffect ( props . onLoad , [ ] ) ;
333-
334356 useEffect ( ( ) => {
335357 const handleKeyDown = e => {
336358 // console.log(`Key down: ${e.keyCode}`);
@@ -648,8 +670,7 @@ const WgpuToyController = props => {
648670 } else if ( props . embed ) {
649671 dimensions = getDimensions ( window . innerWidth * dpr ) ;
650672 } else {
651- const padding = 16 ;
652- dimensions = getDimensions ( ( parentRef ! . offsetWidth - padding ) * dpr ) ;
673+ dimensions = getDimensions ( parentRef ! . offsetWidth * dpr ) ;
653674 }
654675 if ( canvas ) {
655676 canvas . width = dimensions . x ;
0 commit comments