@@ -3,11 +3,15 @@ export function quitIfAdapterNotAvailable(
33 adapter : GPUAdapter | null
44) : asserts adapter {
55 if ( ! ( 'gpu' in navigator ) ) {
6- fail ( 'navigator.gpu is not defined - WebGPU not available in this browser' ) ;
6+ throw fail (
7+ 'navigator.gpu is not defined - WebGPU not available in this browser'
8+ ) ;
79 }
810
911 if ( ! adapter ) {
10- fail ( "requestAdapter returned null - this sample can't run on this system" ) ;
12+ throw fail (
13+ "requestAdapter returned null - this sample can't run on this system"
14+ ) ;
1115 }
1216}
1317
@@ -21,7 +25,7 @@ export function quitIfLimitLessThan(
2125 const limitKey = limit as keyof GPUSupportedLimits ;
2226 const limitValue = adapter . limits [ limitKey ] as number ;
2327 if ( limitValue < requiredValue ) {
24- fail (
28+ throw fail (
2529 `This sample can't run on this system. ${ limit } is ${ limitValue } , and this sample requires at least ${ requiredValue } .`
2630 ) ;
2731 }
@@ -39,8 +43,7 @@ export function quitIfWebGPUNotAvailable(
3943) : asserts device {
4044 if ( ! device ) {
4145 quitIfAdapterNotAvailable ( adapter ) ;
42- fail ( 'Unable to get a device for an unknown reason' ) ;
43- return ;
46+ throw fail ( 'Unable to get a device for an unknown reason' ) ;
4447 }
4548
4649 device . lost . then ( ( reason ) => {
@@ -51,16 +54,46 @@ export function quitIfWebGPUNotAvailable(
5154 } ) ;
5255}
5356
54- /** Fail by showing a console error, and dialog box if possible. */
55- const fail = ( ( ) => {
57+ /**
58+ * Create a MessageChannel, and forward messages to fail() to show an error
59+ * dialog. Return a MessagePort for the worker to send messages back on.
60+ */
61+ export function mainThreadCreateErrorMessagePortForWorker ( ) {
62+ if ( typeof window === 'undefined' ) throw new Error ( 'Called on wrong thread!' ) ;
63+ const mc = new MessageChannel ( ) ;
64+ mc . port1 . onmessage = ( ev : MessageEvent < string > ) => {
65+ fail ( ev . data ) ;
66+ } ;
67+ return mc . port2 ;
68+ }
69+
70+ let errorMessagePort : MessagePort | null = null ;
71+ export function workerRegisterErrorMessagePort ( port : MessagePort ) {
72+ if ( typeof window !== 'undefined' ) throw new Error ( 'Called on wrong thread!' ) ;
73+ errorMessagePort = port ;
74+ }
75+
76+ /**
77+ * Fail by showing a console error, and dialog box if possible.
78+ *
79+ * Returns an Error object, which may be thrown if execution should stop here.
80+ * (Throwing the error will generally trigger one of the global listeners,
81+ * 'unhandledrejection' or 'error', but this won't do anything because the
82+ * dialog is already open at that point, and we don't overwrite it.)
83+ */
84+ const fail : ( message : string ) => Error = ( ( ) => {
5685 type ErrorOutput = { show ( msg : string ) : void } ;
5786
5887 function createErrorOutput ( ) {
5988 if ( typeof document === 'undefined' ) {
60- // Not implemented in workers.
6189 return {
6290 show ( msg : string ) {
63- console . error ( msg ) ;
91+ if ( errorMessagePort ) {
92+ errorMessagePort . postMessage ( msg ) ;
93+ } else {
94+ console . warn ( 'workerRegisterErrorMessagePort has not been called!' ) ;
95+ console . error ( msg ) ;
96+ }
6497 } ,
6598 } ;
6699 }
@@ -96,6 +129,6 @@ const fail = (() => {
96129 if ( ! output ) output = createErrorOutput ( ) ;
97130
98131 output . show ( message ) ;
99- throw new Error ( message ) ;
132+ return new Error ( message ) ;
100133 } ;
101134} ) ( ) ;
0 commit comments