@@ -10,11 +10,16 @@ import {StatsManager} from '../utils/stats-manager';
10
10
import { lumaStats } from '../utils/stats-manager' ;
11
11
import { log } from '../utils/log' ;
12
12
13
+ declare global {
14
+ // eslint-disable-next-line no-var
15
+ var luma : Luma ;
16
+ }
17
+
18
+ const STARTUP_MESSAGE = 'set luma.log.level=1 (or higher) to trace rendering' ;
19
+
13
20
const ERROR_MESSAGE =
14
21
'No matching device found. Ensure `@luma.gl/webgl` and/or `@luma.gl/webgpu` modules are imported.' ;
15
22
16
- const preregisteredAdapters = new Map < string , Adapter > ( ) ;
17
-
18
23
/** Properties for creating a new device */
19
24
export type CreateDeviceProps = DeviceProps & {
20
25
/** Selects the type of device. `best-available` uses webgpu if available, then webgl. */
@@ -25,7 +30,8 @@ export type CreateDeviceProps = DeviceProps & {
25
30
/** Properties for attaching an existing WebGL context or WebGPU device to a new luma Device */
26
31
export type AttachDeviceProps = DeviceProps & {
27
32
/** Externally created WebGL context or WebGPU device */
28
- handle : WebGL2RenderingContext ; // | GPUDevice;
33
+ handle : unknown ; // WebGL2RenderingContext | GPUDevice | null;
34
+ /** List of adapters. Will also search any pre-registered adapterss */
29
35
adapters ?: Adapter [ ] ;
30
36
} ;
31
37
@@ -34,37 +40,67 @@ export type AttachDeviceProps = DeviceProps & {
34
40
* Register WebGPU and/or WebGL adapters (controls application bundle size)
35
41
* Run-time selection of the first available Device
36
42
*/
37
- export class luma {
43
+ export class Luma {
38
44
static defaultProps : Required < CreateDeviceProps > = {
39
45
...Device . defaultProps ,
40
46
type : 'best-available' ,
41
47
adapters : undefined !
42
48
} ;
43
49
44
- /** Global stats for all adapters */
45
- static stats : StatsManager = lumaStats ;
50
+ /** Global stats for all devices */
51
+ readonly stats : StatsManager = lumaStats ;
52
+
53
+ /**
54
+ * Global log
55
+ *
56
+ * Assign luma.log.level in console to control logging: \
57
+ * 0: none, 1: minimal, 2: verbose, 3: attribute/uniforms, 4: gl logs
58
+ * luma.log.break[], set to gl funcs, luma.log.profile[] set to model names`;
59
+ */
60
+ readonly log : Log = log ;
61
+
62
+ /** Version of luma.gl */
63
+ readonly VERSION : string =
64
+ // Version detection using build plugin
65
+ // @ts -expect-error no-undef
66
+ typeof __VERSION__ !== 'undefined' ? __VERSION__ : 'running from source' ;
67
+
68
+ protected preregisteredAdapters = new Map < string , Adapter > ( ) ;
69
+
70
+ constructor ( ) {
71
+ if ( globalThis . luma ) {
72
+ if ( globalThis . luma . VERSION !== this . VERSION ) {
73
+ log . error ( `Found luma.gl ${ globalThis . luma . VERSION } while initialzing ${ this . VERSION } ` ) ( ) ;
74
+ log . error ( `'yarn why @luma.gl/core' can help identify the source of the conflict` ) ( ) ;
75
+ throw new Error ( `luma.gl - multiple versions detected: see console log` ) ;
76
+ }
77
+
78
+ log . error ( 'This version of luma.gl has already been initialized' ) ( ) ;
79
+ }
46
80
47
- /** Global log */
48
- static log : Log = log ;
81
+ log . log ( 1 , `${ this . VERSION } - ${ STARTUP_MESSAGE } ` ) ( ) ;
49
82
50
- static registerAdapters ( adapters : Adapter [ ] ) : void {
83
+ globalThis . luma = this ;
84
+ }
85
+
86
+ registerAdapters ( adapters : Adapter [ ] ) : void {
51
87
for ( const deviceClass of adapters ) {
52
- preregisteredAdapters . set ( deviceClass . type , deviceClass ) ;
88
+ this . preregisteredAdapters . set ( deviceClass . type , deviceClass ) ;
53
89
}
54
90
}
55
91
56
92
/** Get type strings for supported Devices */
57
- static getSupportedAdapters ( adapters : Adapter [ ] = [ ] ) : string [ ] {
58
- const adapterMap = getAdapterMap ( adapters ) ;
93
+ getSupportedAdapters ( adapters : Adapter [ ] = [ ] ) : string [ ] {
94
+ const adapterMap = this . getAdapterMap ( adapters ) ;
59
95
return Array . from ( adapterMap )
60
96
. map ( ( [ , adapter ] ) => adapter )
61
97
. filter ( adapter => adapter . isSupported ?.( ) )
62
98
. map ( adapter => adapter . type ) ;
63
99
}
64
100
65
101
/** Get type strings for best available Device */
66
- static getBestAvailableAdapter ( adapters : Adapter [ ] = [ ] ) : 'webgpu' | 'webgl' | null {
67
- const adapterMap = getAdapterMap ( adapters ) ;
102
+ getBestAvailableAdapter ( adapters : Adapter [ ] = [ ] ) : 'webgpu' | 'webgl' | null {
103
+ const adapterMap = this . getAdapterMap ( adapters ) ;
68
104
if ( adapterMap . get ( 'webgpu' ) ?. isSupported ?.( ) ) {
69
105
return 'webgpu' ;
70
106
}
@@ -74,27 +110,27 @@ export class luma {
74
110
return null ;
75
111
}
76
112
77
- static setDefaultDeviceProps ( props : CreateDeviceProps ) : void {
78
- Object . assign ( luma . defaultProps , props ) ;
113
+ setDefaultDeviceProps ( props : CreateDeviceProps ) : void {
114
+ Object . assign ( Luma . defaultProps , props ) ;
79
115
}
80
116
81
117
/** Creates a device. Asynchronously. */
82
- static async createDevice ( props : CreateDeviceProps = { } ) : Promise < Device > {
83
- props = { ...luma . defaultProps , ...props } ;
118
+ async createDevice ( props : CreateDeviceProps = { } ) : Promise < Device > {
119
+ props = { ...Luma . defaultProps , ...props } ;
84
120
85
121
// Should be handled by attach device
86
122
// if (props.gl) {
87
123
// props.type = 'webgl';
88
124
// }
89
125
90
- const adapterMap = getAdapterMap ( props . adapters ) ;
126
+ const adapterMap = this . getAdapterMap ( props . adapters ) ;
91
127
92
128
let type : string = props . type || '' ;
93
129
if ( type === 'best-available' ) {
94
- type = luma . getBestAvailableAdapter ( props . adapters ) || type ;
130
+ type = this . getBestAvailableAdapter ( props . adapters ) || type ;
95
131
}
96
132
97
- const adapters = getAdapterMap ( props . adapters ) || adapterMap ;
133
+ const adapters = this . getAdapterMap ( props . adapters ) || adapterMap ;
98
134
99
135
const adapter = adapters . get ( type ) ;
100
136
const device = await adapter ?. create ?.( props ) ;
@@ -106,8 +142,8 @@ export class luma {
106
142
}
107
143
108
144
/** Attach to an existing GPU API handle (WebGL2RenderingContext or GPUDevice). */
109
- static async attachDevice ( props : AttachDeviceProps ) : Promise < Device > {
110
- const adapters = getAdapterMap ( props . adapters ) ;
145
+ async attachDevice ( props : AttachDeviceProps ) : Promise < Device > {
146
+ const adapters = this . getAdapterMap ( props . adapters ) ;
111
147
112
148
// WebGL
113
149
let type = '' ;
@@ -142,7 +178,7 @@ export class luma {
142
178
* Used when attaching luma to a context from an external library does not support creating WebGL2 contexts.
143
179
* (luma can only attach to WebGL2 contexts).
144
180
*/
145
- static enforceWebGL2 ( enforce : boolean = true ) : void {
181
+ enforceWebGL2 ( enforce : boolean = true ) : void {
146
182
const prototype = HTMLCanvasElement . prototype as any ;
147
183
if ( ! enforce && prototype . originalGetContext ) {
148
184
// Reset the original getContext function
@@ -168,7 +204,7 @@ export class luma {
168
204
169
205
/** Convert a list of adapters to a map */
170
206
protected getAdapterMap ( adapters : Adapter [ ] = [ ] ) : Map < string , Adapter > {
171
- const map = new Map ( preregisteredAdapters ) ;
207
+ const map = new Map ( this . preregisteredAdapters ) ;
172
208
for ( const adapter of adapters ) {
173
209
map . set ( adapter . type , adapter ) ;
174
210
}
@@ -178,23 +214,20 @@ export class luma {
178
214
// DEPRECATED
179
215
180
216
/** @deprecated Use registerAdapters */
181
- static registerDevices ( deviceClasses : any [ ] ) : void {
217
+ registerDevices ( deviceClasses : any [ ] ) : void {
182
218
log . warn ( 'luma.registerDevices() is deprecated, use luma.registerAdapters() instead' ) ;
183
219
for ( const deviceClass of deviceClasses ) {
184
220
const adapter = deviceClass . adapter as Adapter ;
185
221
if ( adapter ) {
186
- preregisteredAdapters . set ( adapter . type , adapter ) ;
222
+ this . preregisteredAdapters . set ( adapter . type , adapter ) ;
187
223
}
188
224
}
189
225
}
190
226
}
191
227
192
- /** Convert a list of adapters to a map */
193
- function getAdapterMap ( adapters : Adapter [ ] = [ ] ) : Map < string , Adapter > {
194
- const map = new Map < string , Adapter > ( preregisteredAdapters ) ;
195
- for ( const deviceClass of adapters ) {
196
- // assert(deviceClass.type && deviceClass.isSupported && deviceClass.create);
197
- map . set ( deviceClass . type , deviceClass ) ;
198
- }
199
- return map ;
200
- }
228
+ /**
229
+ * Entry point to the luma.gl GPU abstraction
230
+ * Register WebGPU and/or WebGL adapters (controls application bundle size)
231
+ * Run-time selection of the first available Device
232
+ */
233
+ export const luma = new Luma ( ) ;
0 commit comments