@@ -3,11 +3,15 @@ export function quitIfAdapterNotAvailable(
3
3
adapter : GPUAdapter | null
4
4
) : asserts adapter {
5
5
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
+ ) ;
7
9
}
8
10
9
11
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
+ ) ;
11
15
}
12
16
}
13
17
@@ -21,7 +25,7 @@ export function quitIfLimitLessThan(
21
25
const limitKey = limit as keyof GPUSupportedLimits ;
22
26
const limitValue = adapter . limits [ limitKey ] as number ;
23
27
if ( limitValue < requiredValue ) {
24
- fail (
28
+ throw fail (
25
29
`This sample can't run on this system. ${ limit } is ${ limitValue } , and this sample requires at least ${ requiredValue } .`
26
30
) ;
27
31
}
@@ -39,8 +43,7 @@ export function quitIfWebGPUNotAvailable(
39
43
) : asserts device {
40
44
if ( ! device ) {
41
45
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' ) ;
44
47
}
45
48
46
49
device . lost . then ( ( reason ) => {
@@ -51,16 +54,46 @@ export function quitIfWebGPUNotAvailable(
51
54
} ) ;
52
55
}
53
56
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 = ( ( ) => {
56
85
type ErrorOutput = { show ( msg : string ) : void } ;
57
86
58
87
function createErrorOutput ( ) {
59
88
if ( typeof document === 'undefined' ) {
60
- // Not implemented in workers.
61
89
return {
62
90
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
+ }
64
97
} ,
65
98
} ;
66
99
}
@@ -96,6 +129,6 @@ const fail = (() => {
96
129
if ( ! output ) output = createErrorOutput ( ) ;
97
130
98
131
output . show ( message ) ;
99
- throw new Error ( message ) ;
132
+ return new Error ( message ) ;
100
133
} ;
101
134
} ) ( ) ;
0 commit comments