@luma.gl/webgl 9.3.0-alpha.2 → 9.3.0-alpha.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. package/dist/adapter/converters/webgl-texture-table.d.ts +7 -1
  2. package/dist/adapter/converters/webgl-texture-table.d.ts.map +1 -1
  3. package/dist/adapter/converters/webgl-texture-table.js +121 -43
  4. package/dist/adapter/converters/webgl-texture-table.js.map +1 -1
  5. package/dist/adapter/device-helpers/webgl-device-features.d.ts.map +1 -1
  6. package/dist/adapter/device-helpers/webgl-device-features.js +1 -2
  7. package/dist/adapter/device-helpers/webgl-device-features.js.map +1 -1
  8. package/dist/adapter/device-helpers/webgl-device-info.js +5 -0
  9. package/dist/adapter/device-helpers/webgl-device-info.js.map +1 -1
  10. package/dist/adapter/helpers/get-shader-layout-from-glsl.js +23 -21
  11. package/dist/adapter/helpers/get-shader-layout-from-glsl.js.map +1 -1
  12. package/dist/adapter/helpers/parse-shader-compiler-log.d.ts +1 -1
  13. package/dist/adapter/helpers/parse-shader-compiler-log.d.ts.map +1 -1
  14. package/dist/adapter/helpers/parse-shader-compiler-log.js +20 -0
  15. package/dist/adapter/helpers/parse-shader-compiler-log.js.map +1 -1
  16. package/dist/adapter/resources/webgl-buffer.d.ts.map +1 -1
  17. package/dist/adapter/resources/webgl-buffer.js +19 -4
  18. package/dist/adapter/resources/webgl-buffer.js.map +1 -1
  19. package/dist/adapter/resources/webgl-command-buffer.d.ts +3 -4
  20. package/dist/adapter/resources/webgl-command-buffer.d.ts.map +1 -1
  21. package/dist/adapter/resources/webgl-command-buffer.js +11 -7
  22. package/dist/adapter/resources/webgl-command-buffer.js.map +1 -1
  23. package/dist/adapter/resources/webgl-command-encoder.d.ts +5 -4
  24. package/dist/adapter/resources/webgl-command-encoder.d.ts.map +1 -1
  25. package/dist/adapter/resources/webgl-command-encoder.js +20 -7
  26. package/dist/adapter/resources/webgl-command-encoder.js.map +1 -1
  27. package/dist/adapter/resources/webgl-query-set.d.ts +29 -31
  28. package/dist/adapter/resources/webgl-query-set.d.ts.map +1 -1
  29. package/dist/adapter/resources/webgl-query-set.js +193 -97
  30. package/dist/adapter/resources/webgl-query-set.js.map +1 -1
  31. package/dist/adapter/resources/webgl-render-pass.d.ts.map +1 -1
  32. package/dist/adapter/resources/webgl-render-pass.js +17 -0
  33. package/dist/adapter/resources/webgl-render-pass.js.map +1 -1
  34. package/dist/adapter/resources/webgl-render-pipeline.d.ts +13 -19
  35. package/dist/adapter/resources/webgl-render-pipeline.d.ts.map +1 -1
  36. package/dist/adapter/resources/webgl-render-pipeline.js +36 -154
  37. package/dist/adapter/resources/webgl-render-pipeline.js.map +1 -1
  38. package/dist/adapter/resources/webgl-shared-render-pipeline.d.ts +24 -0
  39. package/dist/adapter/resources/webgl-shared-render-pipeline.d.ts.map +1 -0
  40. package/dist/adapter/resources/webgl-shared-render-pipeline.js +152 -0
  41. package/dist/adapter/resources/webgl-shared-render-pipeline.js.map +1 -0
  42. package/dist/adapter/resources/webgl-texture.d.ts +23 -4
  43. package/dist/adapter/resources/webgl-texture.d.ts.map +1 -1
  44. package/dist/adapter/resources/webgl-texture.js +203 -100
  45. package/dist/adapter/resources/webgl-texture.js.map +1 -1
  46. package/dist/adapter/resources/webgl-transform-feedback.js +5 -5
  47. package/dist/adapter/resources/webgl-transform-feedback.js.map +1 -1
  48. package/dist/adapter/webgl-adapter.d.ts.map +1 -1
  49. package/dist/adapter/webgl-adapter.js +3 -4
  50. package/dist/adapter/webgl-adapter.js.map +1 -1
  51. package/dist/adapter/webgl-device.d.ts +6 -3
  52. package/dist/adapter/webgl-device.d.ts.map +1 -1
  53. package/dist/adapter/webgl-device.js +56 -14
  54. package/dist/adapter/webgl-device.js.map +1 -1
  55. package/dist/adapter/webgl-presentation-context.d.ts +21 -0
  56. package/dist/adapter/webgl-presentation-context.d.ts.map +1 -0
  57. package/dist/adapter/webgl-presentation-context.js +64 -0
  58. package/dist/adapter/webgl-presentation-context.js.map +1 -0
  59. package/dist/context/debug/spector.d.ts.map +1 -1
  60. package/dist/context/debug/spector.js +4 -4
  61. package/dist/context/debug/spector.js.map +1 -1
  62. package/dist/context/debug/webgl-developer-tools.js +2 -0
  63. package/dist/context/debug/webgl-developer-tools.js.map +1 -1
  64. package/dist/context/helpers/create-browser-context.d.ts.map +1 -1
  65. package/dist/context/helpers/create-browser-context.js +6 -8
  66. package/dist/context/helpers/create-browser-context.js.map +1 -1
  67. package/dist/context/helpers/webgl-context-data.d.ts +5 -1
  68. package/dist/context/helpers/webgl-context-data.d.ts.map +1 -1
  69. package/dist/context/helpers/webgl-context-data.js +9 -10
  70. package/dist/context/helpers/webgl-context-data.js.map +1 -1
  71. package/dist/context/parameters/unified-parameter-api.d.ts +1 -1
  72. package/dist/context/parameters/unified-parameter-api.js +2 -2
  73. package/dist/context/parameters/unified-parameter-api.js.map +1 -1
  74. package/dist/context/state-tracker/webgl-state-tracker.js +2 -2
  75. package/dist/context/state-tracker/webgl-state-tracker.js.map +1 -1
  76. package/dist/dist.dev.js +1427 -828
  77. package/dist/dist.min.js +2 -2
  78. package/dist/index.cjs +1325 -811
  79. package/dist/index.cjs.map +4 -4
  80. package/dist/utils/fill-array.js +1 -1
  81. package/dist/utils/fill-array.js.map +1 -1
  82. package/package.json +4 -4
  83. package/src/adapter/converters/webgl-texture-table.ts +159 -47
  84. package/src/adapter/device-helpers/webgl-device-features.ts +1 -2
  85. package/src/adapter/device-helpers/webgl-device-info.ts +6 -0
  86. package/src/adapter/helpers/get-shader-layout-from-glsl.ts +25 -24
  87. package/src/adapter/helpers/parse-shader-compiler-log.ts +23 -1
  88. package/src/adapter/resources/webgl-buffer.ts +16 -4
  89. package/src/adapter/resources/webgl-command-buffer.ts +21 -24
  90. package/src/adapter/resources/webgl-command-encoder.ts +22 -7
  91. package/src/adapter/resources/webgl-query-set.ts +229 -102
  92. package/src/adapter/resources/webgl-render-pass.ts +19 -0
  93. package/src/adapter/resources/webgl-render-pipeline.ts +46 -181
  94. package/src/adapter/resources/webgl-shared-render-pipeline.ts +208 -0
  95. package/src/adapter/resources/webgl-texture.ts +326 -121
  96. package/src/adapter/resources/webgl-transform-feedback.ts +5 -5
  97. package/src/adapter/webgl-adapter.ts +3 -4
  98. package/src/adapter/webgl-device.ts +66 -19
  99. package/src/adapter/webgl-presentation-context.ts +93 -0
  100. package/src/context/debug/spector.ts +4 -4
  101. package/src/context/debug/webgl-developer-tools.ts +2 -0
  102. package/src/context/helpers/create-browser-context.ts +8 -8
  103. package/src/context/helpers/webgl-context-data.ts +17 -11
  104. package/src/context/parameters/unified-parameter-api.ts +2 -2
  105. package/src/context/state-tracker/webgl-state-tracker.ts +2 -2
  106. package/src/utils/fill-array.ts +1 -1
@@ -8,7 +8,7 @@ export function fillArray(options) {
8
8
  const total = count * length;
9
9
  let copied = 0;
10
10
  for (let i = start; copied < length; copied++) {
11
- target[i++] = source[copied];
11
+ target[i++] = source[copied] ?? 0;
12
12
  }
13
13
  while (copied < total) {
14
14
  // If we have copied less than half, copy everything we got
@@ -1 +1 @@
1
- {"version":3,"file":"fill-array.js","sourceRoot":"","sources":["../../src/utils/fill-array.ts"],"names":[],"mappings":"AAAA,UAAU;AACV,+BAA+B;AAC/B,oCAAoC;AAIpC,sEAAsE;AACtE,MAAM,UAAU,SAAS,CAAC,OAKzB;IACC,MAAM,EAAC,MAAM,EAAE,MAAM,EAAE,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,CAAC,EAAC,GAAG,OAAO,CAAC;IACvD,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;IAC7B,MAAM,KAAK,GAAG,KAAK,GAAG,MAAM,CAAC;IAC7B,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,KAAK,IAAI,CAAC,GAAG,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC;QAC9C,MAAM,CAAC,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;IAC/B,CAAC;IAED,OAAO,MAAM,GAAG,KAAK,EAAE,CAAC;QACtB,2DAA2D;QAC3D,uCAAuC;QACvC,IAAI,MAAM,GAAG,KAAK,GAAG,MAAM,EAAE,CAAC;YAC5B,MAAM,CAAC,UAAU,CAAC,KAAK,GAAG,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,MAAM,CAAC,CAAC;YACzD,MAAM,IAAI,CAAC,CAAC;QACd,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,UAAU,CAAC,KAAK,GAAG,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,KAAK,GAAG,MAAM,CAAC,CAAC;YACjE,MAAM,GAAG,KAAK,CAAC;QACjB,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC,MAAM,CAAC;AACxB,CAAC"}
1
+ {"version":3,"file":"fill-array.js","sourceRoot":"","sources":["../../src/utils/fill-array.ts"],"names":[],"mappings":"AAAA,UAAU;AACV,+BAA+B;AAC/B,oCAAoC;AAIpC,sEAAsE;AACtE,MAAM,UAAU,SAAS,CAAC,OAKzB;IACC,MAAM,EAAC,MAAM,EAAE,MAAM,EAAE,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,CAAC,EAAC,GAAG,OAAO,CAAC;IACvD,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;IAC7B,MAAM,KAAK,GAAG,KAAK,GAAG,MAAM,CAAC;IAC7B,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,KAAK,IAAI,CAAC,GAAG,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC;QAC9C,MAAM,CAAC,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC;IAED,OAAO,MAAM,GAAG,KAAK,EAAE,CAAC;QACtB,2DAA2D;QAC3D,uCAAuC;QACvC,IAAI,MAAM,GAAG,KAAK,GAAG,MAAM,EAAE,CAAC;YAC5B,MAAM,CAAC,UAAU,CAAC,KAAK,GAAG,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,MAAM,CAAC,CAAC;YACzD,MAAM,IAAI,CAAC,CAAC;QACd,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,UAAU,CAAC,KAAK,GAAG,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,KAAK,GAAG,MAAM,CAAC,CAAC;YACjE,MAAM,GAAG,KAAK,CAAC;QACjB,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC,MAAM,CAAC;AACxB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@luma.gl/webgl",
3
- "version": "9.3.0-alpha.2",
3
+ "version": "9.3.0-alpha.6",
4
4
  "description": "WebGL2 adapter for the luma.gl core API",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -43,9 +43,9 @@
43
43
  "@luma.gl/core": "9.2.0-alpha.6"
44
44
  },
45
45
  "dependencies": {
46
- "@luma.gl/constants": "9.3.0-alpha.2",
46
+ "@luma.gl/constants": "9.3.0-alpha.6",
47
47
  "@math.gl/types": "^4.1.0",
48
- "@probe.gl/env": "^4.0.8"
48
+ "@probe.gl/env": "^4.1.1"
49
49
  },
50
- "gitHead": "7fedf8d8902f58490a4ffca9a873daee3c732f24"
50
+ "gitHead": "59fda5480c4d0bb3d64545d4621175221f2b6c7c"
51
51
  }
@@ -32,32 +32,44 @@ const X_ATC = 'WEBGL_compressed_texture_atc';
32
32
  const EXT_texture_norm16 = 'EXT_texture_norm16';
33
33
  const EXT_render_snorm = 'EXT_render_snorm';
34
34
  const EXT_color_buffer_float = 'EXT_color_buffer_float';
35
+ const SNORM8_COLOR_RENDERABLE: DeviceFeature = 'snorm8-renderable-webgl';
36
+ const NORM16_COLOR_RENDERABLE: DeviceFeature = 'norm16-renderable-webgl';
37
+ const SNORM16_COLOR_RENDERABLE: DeviceFeature = 'snorm16-renderable-webgl';
38
+ const FLOAT16_COLOR_RENDERABLE: DeviceFeature = 'float16-renderable-webgl';
39
+ const FLOAT32_COLOR_RENDERABLE: DeviceFeature = 'float32-renderable-webgl';
40
+ const RGB9E5UFLOAT_COLOR_RENDERABLE: DeviceFeature = 'rgb9e5ufloat-renderable-webgl';
41
+
42
+ type TextureFeatureDefinition = {
43
+ extensions?: string[];
44
+ features?: DeviceFeature[];
45
+ };
35
46
 
36
47
  // prettier-ignore
37
- export const TEXTURE_FEATURES: Partial<Record<DeviceFeature, string[]>> = {
38
- 'float32-renderable-webgl': ['EXT_color_buffer_float'],
39
- 'float16-renderable-webgl': ['EXT_color_buffer_half_float'],
40
- 'rgb9e5ufloat-renderable-webgl': ['WEBGL_render_shared_exponent'],
41
- 'snorm8-renderable-webgl': [EXT_render_snorm],
42
- 'norm16-renderable-webgl': [EXT_texture_norm16],
43
- 'snorm16-renderable-webgl': [EXT_texture_norm16, EXT_render_snorm],
44
-
45
- 'float32-filterable': ['OES_texture_float_linear'],
46
- 'float16-filterable-webgl': ['OES_texture_half_float_linear'],
47
- 'texture-filterable-anisotropic-webgl': ['EXT_texture_filter_anisotropic'],
48
-
49
- 'texture-blend-float-webgl': ['EXT_float_blend'],
50
-
51
- 'texture-compression-bc': [X_S3TC, X_S3TC_SRGB, X_RGTC, X_BPTC],
48
+ export const TEXTURE_FEATURES: Partial<Record<DeviceFeature, TextureFeatureDefinition>> = {
49
+ 'float32-renderable-webgl': {extensions: [EXT_color_buffer_float]},
50
+ 'float16-renderable-webgl': {extensions: ['EXT_color_buffer_half_float']},
51
+ 'rgb9e5ufloat-renderable-webgl': {extensions: ['WEBGL_render_shared_exponent']},
52
+ 'snorm8-renderable-webgl': {extensions: [EXT_render_snorm]},
53
+ 'norm16-webgl': {extensions: [EXT_texture_norm16]},
54
+ 'norm16-renderable-webgl': {features: ['norm16-webgl']},
55
+ 'snorm16-renderable-webgl': {features: ['norm16-webgl'], extensions: [EXT_render_snorm]},
56
+
57
+ 'float32-filterable': {extensions: ['OES_texture_float_linear']},
58
+ 'float16-filterable-webgl': {extensions: ['OES_texture_half_float_linear']},
59
+ 'texture-filterable-anisotropic-webgl': {extensions: ['EXT_texture_filter_anisotropic']},
60
+
61
+ 'texture-blend-float-webgl': {extensions: ['EXT_float_blend']},
62
+
63
+ 'texture-compression-bc': {extensions: [X_S3TC, X_S3TC_SRGB, X_RGTC, X_BPTC]},
52
64
  // 'texture-compression-bc3-srgb-webgl': [X_S3TC_SRGB],
53
65
  // 'texture-compression-bc3-webgl': [X_S3TC],
54
- 'texture-compression-bc5-webgl': [X_RGTC],
55
- 'texture-compression-bc7-webgl': [X_BPTC],
56
- 'texture-compression-etc2': [X_ETC2],
57
- 'texture-compression-astc': [X_ASTC],
58
- 'texture-compression-etc1-webgl': [X_ETC1],
59
- 'texture-compression-pvrtc-webgl': [X_PVRTC],
60
- 'texture-compression-atc-webgl': [X_ATC]
66
+ 'texture-compression-bc5-webgl': {extensions: [X_RGTC]},
67
+ 'texture-compression-bc7-webgl': {extensions: [X_BPTC]},
68
+ 'texture-compression-etc2': {extensions: [X_ETC2]},
69
+ 'texture-compression-astc': {extensions: [X_ASTC]},
70
+ 'texture-compression-etc1-webgl': {extensions: [X_ETC1]},
71
+ 'texture-compression-pvrtc-webgl': {extensions: [X_PVRTC]},
72
+ 'texture-compression-atc-webgl': {extensions: [X_ATC]}
61
73
  };
62
74
 
63
75
  export function isTextureFeature(feature: DeviceFeature): boolean {
@@ -70,8 +82,36 @@ export function checkTextureFeature(
70
82
  feature: DeviceFeature,
71
83
  extensions: GLExtensions
72
84
  ): boolean {
73
- const textureExtensions = TEXTURE_FEATURES[feature] || [];
74
- return textureExtensions.every(extension => getWebGLExtension(gl, extension, extensions));
85
+ return hasTextureFeature(gl, feature, extensions, new Set<DeviceFeature>());
86
+ }
87
+
88
+ function hasTextureFeature(
89
+ gl: WebGL2RenderingContext,
90
+ feature: DeviceFeature,
91
+ extensions: GLExtensions,
92
+ seenFeatures: Set<DeviceFeature>
93
+ ): boolean {
94
+ const definition = TEXTURE_FEATURES[feature];
95
+ if (!definition) {
96
+ return false;
97
+ }
98
+
99
+ if (seenFeatures.has(feature)) {
100
+ return false;
101
+ }
102
+
103
+ seenFeatures.add(feature);
104
+ const hasDependentFeatures = (definition.features || []).every(dependentFeature =>
105
+ hasTextureFeature(gl, dependentFeature, extensions, seenFeatures)
106
+ );
107
+ seenFeatures.delete(feature);
108
+ if (!hasDependentFeatures) {
109
+ return false;
110
+ }
111
+
112
+ return (definition.extensions || []).every(extension =>
113
+ Boolean(getWebGLExtension(gl, extension, extensions))
114
+ );
75
115
  }
76
116
 
77
117
  // TEXTURE FORMATS
@@ -81,6 +121,8 @@ type WebGLFormatInfo = {
81
121
  gl?: GL;
82
122
  /** compressed */
83
123
  x?: string;
124
+ /** color-renderable capability gate. false means never color-renderable on WebGL. */
125
+ r?: DeviceFeature | false;
84
126
  types?: GLPixelType[];
85
127
  dataFormat?: GLTexelDataFormat;
86
128
  /** if depthTexture is set this is a depth/stencil format that can be set to a texture */
@@ -99,21 +141,21 @@ type WebGLFormatInfo = {
99
141
  export const WEBGL_TEXTURE_FORMATS: Record<TextureFormat, WebGLFormatInfo> = {
100
142
  // 8-bit formats
101
143
  'r8unorm': {gl: GL.R8, rb: true},
102
- 'r8snorm': {gl: GL.R8_SNORM},
144
+ 'r8snorm': {gl: GL.R8_SNORM, r: SNORM8_COLOR_RENDERABLE},
103
145
  'r8uint': {gl: GL.R8UI, rb: true},
104
146
  'r8sint': {gl: GL.R8I, rb: true},
105
147
 
106
148
  // 16-bit formats
107
149
  'rg8unorm': {gl: GL.RG8, rb: true},
108
- 'rg8snorm': {gl: GL.RG8_SNORM},
150
+ 'rg8snorm': {gl: GL.RG8_SNORM, r: SNORM8_COLOR_RENDERABLE},
109
151
  'rg8uint': {gl: GL.RG8UI, rb: true},
110
152
  'rg8sint': {gl: GL.RG8I, rb: true},
111
153
 
112
154
  'r16uint': {gl: GL.R16UI, rb: true},
113
155
  'r16sint': {gl: GL.R16I, rb: true},
114
- 'r16float': {gl: GL.R16F, rb: true},
115
- 'r16unorm': {gl: GL.R16_EXT, rb: true},
116
- 'r16snorm': {gl: GL.R16_SNORM_EXT},
156
+ 'r16float': {gl: GL.R16F, rb: true, r: FLOAT16_COLOR_RENDERABLE},
157
+ 'r16unorm': {gl: GL.R16_EXT, rb: true, r: NORM16_COLOR_RENDERABLE},
158
+ 'r16snorm': {gl: GL.R16_SNORM_EXT, r: SNORM16_COLOR_RENDERABLE},
117
159
 
118
160
  // Packed 16-bit formats
119
161
  'rgba4unorm-webgl': {gl: GL.RGBA4, rb: true},
@@ -127,7 +169,7 @@ export const WEBGL_TEXTURE_FORMATS: Record<TextureFormat, WebGLFormatInfo> = {
127
169
  // 32-bit formats
128
170
  'rgba8unorm': {gl: GL.RGBA8},
129
171
  'rgba8unorm-srgb': {gl: GL.SRGB8_ALPHA8},
130
- 'rgba8snorm': {gl: GL.RGBA8_SNORM},
172
+ 'rgba8snorm': {gl: GL.RGBA8_SNORM, r: SNORM8_COLOR_RENDERABLE},
131
173
  'rgba8uint': {gl: GL.RGBA8UI},
132
174
  'rgba8sint': {gl: GL.RGBA8I},
133
175
  // reverse colors, webgpu only
@@ -136,41 +178,41 @@ export const WEBGL_TEXTURE_FORMATS: Record<TextureFormat, WebGLFormatInfo> = {
136
178
 
137
179
  'rg16uint': {gl: GL.RG16UI},
138
180
  'rg16sint': {gl: GL.RG16I},
139
- 'rg16float': {gl: GL.RG16F, rb: true},
140
- 'rg16unorm': {gl: GL.RG16_EXT},
141
- 'rg16snorm': {gl: GL.RG16_SNORM_EXT},
181
+ 'rg16float': {gl: GL.RG16F, rb: true, r: FLOAT16_COLOR_RENDERABLE},
182
+ 'rg16unorm': {gl: GL.RG16_EXT, r: NORM16_COLOR_RENDERABLE},
183
+ 'rg16snorm': {gl: GL.RG16_SNORM_EXT, r: SNORM16_COLOR_RENDERABLE},
142
184
 
143
185
  'r32uint': {gl: GL.R32UI, rb: true},
144
186
  'r32sint': {gl: GL.R32I, rb: true},
145
- 'r32float': {gl: GL.R32F},
187
+ 'r32float': {gl: GL.R32F, r: FLOAT32_COLOR_RENDERABLE},
146
188
 
147
189
  // Packed 32-bit formats
148
- 'rgb9e5ufloat': {gl: GL.RGB9_E5}, // , filter: true},
190
+ 'rgb9e5ufloat': {gl: GL.RGB9_E5, r: RGB9E5UFLOAT_COLOR_RENDERABLE}, // , filter: true},
149
191
  'rg11b10ufloat': {gl: GL.R11F_G11F_B10F, rb: true},
150
192
  'rgb10a2unorm': {gl: GL.RGB10_A2, rb: true},
151
193
  'rgb10a2uint': {gl: GL.RGB10_A2UI, rb: true},
152
194
 
153
195
  // 48-bit formats
154
- 'rgb16unorm-webgl': {gl: GL.RGB16_EXT}, // rgb not renderable
155
- 'rgb16snorm-webgl': {gl: GL.RGB16_SNORM_EXT}, // rgb not renderable
196
+ 'rgb16unorm-webgl': {gl: GL.RGB16_EXT, r: false}, // rgb not renderable
197
+ 'rgb16snorm-webgl': {gl: GL.RGB16_SNORM_EXT, r: false}, // rgb not renderable
156
198
 
157
199
  // 64-bit formats
158
200
  'rg32uint': {gl: GL.RG32UI, rb: true},
159
201
  'rg32sint': {gl: GL.RG32I, rb: true},
160
- 'rg32float': {gl: GL.RG32F, rb: true},
202
+ 'rg32float': {gl: GL.RG32F, rb: true, r: FLOAT32_COLOR_RENDERABLE},
161
203
  'rgba16uint': {gl: GL.RGBA16UI, rb: true},
162
204
  'rgba16sint': {gl: GL.RGBA16I, rb: true},
163
- 'rgba16float': {gl: GL.RGBA16F},
164
- 'rgba16unorm': {gl: GL.RGBA16_EXT, rb: true},
165
- 'rgba16snorm': {gl: GL.RGBA16_SNORM_EXT},
205
+ 'rgba16float': {gl: GL.RGBA16F, r: FLOAT16_COLOR_RENDERABLE},
206
+ 'rgba16unorm': {gl: GL.RGBA16_EXT, rb: true, r: NORM16_COLOR_RENDERABLE},
207
+ 'rgba16snorm': {gl: GL.RGBA16_SNORM_EXT, r: SNORM16_COLOR_RENDERABLE},
166
208
 
167
209
  // 96-bit formats (deprecated!)
168
- 'rgb32float-webgl': {gl: GL.RGB32F, x: EXT_color_buffer_float, dataFormat: GL.RGB, types: [GL.FLOAT]},
210
+ 'rgb32float-webgl': {gl: GL.RGB32F, x: EXT_color_buffer_float, r: FLOAT32_COLOR_RENDERABLE, dataFormat: GL.RGB, types: [GL.FLOAT]},
169
211
 
170
212
  // 128-bit formats
171
213
  'rgba32uint': {gl: GL.RGBA32UI, rb: true},
172
214
  'rgba32sint': {gl: GL.RGBA32I, rb: true},
173
- 'rgba32float': {gl: GL.RGBA32F, rb: true},
215
+ 'rgba32float': {gl: GL.RGBA32F, rb: true, r: FLOAT32_COLOR_RENDERABLE},
174
216
 
175
217
  // Depth and stencil formats
176
218
  'stencil8': {gl: GL.STENCIL_INDEX8, rb: true}, // 8 stencil bits
@@ -237,8 +279,8 @@ export const WEBGL_TEXTURE_FORMATS: Record<TextureFormat, WebGLFormatInfo> = {
237
279
  'astc-8x6-unorm-srgb': {gl: GL.COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR},
238
280
  'astc-8x8-unorm': {gl: GL.COMPRESSED_RGBA_ASTC_8x8_KHR},
239
281
  'astc-8x8-unorm-srgb': {gl: GL.COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR},
240
- 'astc-10x5-unorm': {gl: GL.COMPRESSED_RGBA_ASTC_10x10_KHR},
241
- 'astc-10x5-unorm-srgb': {gl: GL.COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR},
282
+ 'astc-10x5-unorm': {gl: GL.COMPRESSED_RGBA_ASTC_10x5_KHR},
283
+ 'astc-10x5-unorm-srgb': {gl: GL.COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR},
242
284
  'astc-10x6-unorm': {gl: GL.COMPRESSED_RGBA_ASTC_10x6_KHR},
243
285
  'astc-10x6-unorm-srgb': {gl: GL.COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR},
244
286
  'astc-10x8-unorm': {gl: GL.COMPRESSED_RGBA_ASTC_10x8_KHR},
@@ -254,7 +296,7 @@ export const WEBGL_TEXTURE_FORMATS: Record<TextureFormat, WebGLFormatInfo> = {
254
296
 
255
297
  'pvrtc-rgb4unorm-webgl': {gl: GL.COMPRESSED_RGB_PVRTC_4BPPV1_IMG},
256
298
  'pvrtc-rgba4unorm-webgl': {gl: GL.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG},
257
- 'pvrtc-rbg2unorm-webgl': {gl: GL.COMPRESSED_RGB_PVRTC_2BPPV1_IMG},
299
+ 'pvrtc-rgb2unorm-webgl': {gl: GL.COMPRESSED_RGB_PVRTC_2BPPV1_IMG},
258
300
  'pvrtc-rgba2unorm-webgl': {gl: GL.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG},
259
301
 
260
302
  // WEBGL_compressed_texture_etc1
@@ -308,12 +350,29 @@ export function getTextureFormatCapabilitiesWebGL(
308
350
  supported = supported && Boolean(getWebGLExtension(gl, webglFormatInfo.x, extensions));
309
351
  }
310
352
 
353
+ // WebGL2 exposes STENCIL_INDEX8 for renderbuffers, but standalone stencil textures are not
354
+ // valid texture storage targets. Report them as unsupported texture formats to avoid invalid
355
+ // constructor paths and misleading capability checks.
356
+ if (formatSupport.format === 'stencil8') {
357
+ supported = false;
358
+ }
359
+
360
+ const renderFeatureSupported =
361
+ webglFormatInfo?.r === false
362
+ ? false
363
+ : webglFormatInfo?.r === undefined || checkTextureFeature(gl, webglFormatInfo.r, extensions);
364
+ const renderable =
365
+ supported &&
366
+ formatSupport.render &&
367
+ renderFeatureSupported &&
368
+ isColorRenderableTextureFormat(gl, formatSupport.format, extensions);
369
+
311
370
  return {
312
371
  format: formatSupport.format,
313
372
  // @ts-ignore
314
373
  create: supported && formatSupport.create,
315
374
  // @ts-ignore
316
- render: supported && formatSupport.render,
375
+ render: renderable,
317
376
  // @ts-ignore
318
377
  filter: supported && formatSupport.filter,
319
378
  // @ts-ignore
@@ -323,6 +382,59 @@ export function getTextureFormatCapabilitiesWebGL(
323
382
  };
324
383
  }
325
384
 
385
+ function isColorRenderableTextureFormat(
386
+ gl: WebGL2RenderingContext,
387
+ format: TextureFormat,
388
+ extensions: GLExtensions
389
+ ): boolean {
390
+ const webglFormatInfo = WEBGL_TEXTURE_FORMATS[format];
391
+ const internalFormat = webglFormatInfo?.gl;
392
+ if (internalFormat === undefined) {
393
+ return false;
394
+ }
395
+
396
+ if (webglFormatInfo?.x && !getWebGLExtension(gl, webglFormatInfo.x, extensions)) {
397
+ return false;
398
+ }
399
+
400
+ const previousTexture = gl.getParameter(GL.TEXTURE_BINDING_2D) as WebGLTexture | null;
401
+ const previousFramebuffer = gl.getParameter(GL.FRAMEBUFFER_BINDING) as WebGLFramebuffer | null;
402
+ const texture = gl.createTexture();
403
+ const framebuffer = gl.createFramebuffer();
404
+ if (!texture || !framebuffer) {
405
+ return false;
406
+ }
407
+
408
+ // Isolate the probe from any prior driver errors so the result reflects only this format.
409
+ const noError = Number(GL.NO_ERROR);
410
+ let error = Number(gl.getError());
411
+ while (error !== noError) {
412
+ error = gl.getError();
413
+ }
414
+
415
+ let renderable = false;
416
+ try {
417
+ gl.bindTexture(GL.TEXTURE_2D, texture);
418
+ gl.texStorage2D(GL.TEXTURE_2D, 1, internalFormat, 1, 1);
419
+ if (Number(gl.getError()) !== noError) {
420
+ return false;
421
+ }
422
+
423
+ gl.bindFramebuffer(GL.FRAMEBUFFER, framebuffer);
424
+ gl.framebufferTexture2D(GL.FRAMEBUFFER, GL.COLOR_ATTACHMENT0, GL.TEXTURE_2D, texture, 0);
425
+ renderable =
426
+ Number(gl.checkFramebufferStatus(GL.FRAMEBUFFER)) === Number(GL.FRAMEBUFFER_COMPLETE) &&
427
+ Number(gl.getError()) === noError;
428
+ } finally {
429
+ gl.bindFramebuffer(GL.FRAMEBUFFER, previousFramebuffer);
430
+ gl.deleteFramebuffer(framebuffer);
431
+ gl.bindTexture(GL.TEXTURE_2D, previousTexture);
432
+ gl.deleteTexture(texture);
433
+ }
434
+
435
+ return renderable;
436
+ }
437
+
326
438
  /** Get parameters necessary to work with format in WebGL: internalFormat, dataFormat, type, compressed, */
327
439
  export function getTextureFormatWebGL(format: TextureFormat): {
328
440
  internalFormat: GL;
@@ -21,13 +21,12 @@ import {
21
21
  const WEBGL_FEATURES: Partial<Record<DeviceFeature, boolean | string>> = {
22
22
  // optional WebGPU features
23
23
  'depth-clip-control': 'EXT_depth_clamp', // TODO these seem subtly different
24
- // 'timestamp-query' // GPUQueryType "timestamp-query"
24
+ 'timestamp-query': 'EXT_disjoint_timer_query_webgl2',
25
25
  // "indirect-first-instance"
26
26
  // Textures are handled by getTextureFeatures()
27
27
  // 'depth32float-stencil8' // GPUTextureFormat 'depth32float-stencil8'
28
28
 
29
29
  // optional WebGL features
30
- 'timer-query-webgl': 'EXT_disjoint_timer_query_webgl2',
31
30
  'compilation-status-async-webgl': 'KHR_parallel_shader_compile',
32
31
  'polygon-mode-webgl': 'WEBGL_polygon_mode',
33
32
  'provoking-vertex-webgl': 'WEBGL_provoking_vertex',
@@ -99,6 +99,8 @@ function identifyGPUType(
99
99
 
100
100
  const gpuVendor = identifyGPUVendor(vendor, renderer);
101
101
  switch (gpuVendor) {
102
+ case 'apple':
103
+ return isAppleSiliconGPU(vendor, renderer) ? 'integrated' : 'unknown';
102
104
  case 'intel':
103
105
  return 'integrated';
104
106
  case 'software':
@@ -109,3 +111,7 @@ function identifyGPUType(
109
111
  return 'discrete';
110
112
  }
111
113
  }
114
+
115
+ function isAppleSiliconGPU(vendor: string, renderer: string): boolean {
116
+ return /Apple (M\d|A\d|GPU)/i.test(`${vendor} ${renderer}`);
117
+ }
@@ -10,7 +10,7 @@ import type {
10
10
  VaryingBinding,
11
11
  AttributeShaderType
12
12
  } from '@luma.gl/core';
13
- import {getVariableShaderTypeInfo} from '@luma.gl/core';
13
+ import {getVariableShaderTypeInfo, assertDefined} from '@luma.gl/core';
14
14
 
15
15
  import {GL, GLUniformType} from '@luma.gl/constants';
16
16
  import {
@@ -252,23 +252,26 @@ function readUniformBlocks(
252
252
  // ); // Array of GLint indicating the strides between columns of a column-major matrix or a row-major matrix.
253
253
  // const uniformRowMajor = gl.getActiveUniforms(program, uniformIndices, GL.UNIFORM_IS_ROW_MAJOR);
254
254
  for (let i = 0; i < blockInfo.uniformCount; ++i) {
255
- const activeInfo = gl.getActiveUniform(program, uniformIndices[i]);
256
- if (!activeInfo) {
257
- throw new Error('activeInfo');
255
+ const uniformIndex = uniformIndices[i];
256
+ if (uniformIndex !== undefined) {
257
+ const activeInfo = gl.getActiveUniform(program, uniformIndex);
258
+ if (!activeInfo) {
259
+ throw new Error('activeInfo');
260
+ }
261
+
262
+ const format = convertGLUniformTypeToShaderVariableType(uniformType[i]);
263
+
264
+ blockInfo.uniforms.push({
265
+ name: activeInfo.name,
266
+ format,
267
+ type: uniformType[i],
268
+ arrayLength: uniformArrayLength[i],
269
+ byteOffset: uniformOffset[i],
270
+ byteStride: uniformStride[i]
271
+ // matrixStride: uniformStride[i],
272
+ // rowMajor: uniformRowMajor[i]
273
+ });
258
274
  }
259
-
260
- const format = convertGLUniformTypeToShaderVariableType(uniformType[i]);
261
-
262
- blockInfo.uniforms.push({
263
- name: activeInfo.name,
264
- format,
265
- type: uniformType[i],
266
- arrayLength: uniformArrayLength[i],
267
- byteOffset: uniformOffset[i],
268
- byteStride: uniformStride[i]
269
- // matrixStride: uniformStride[i],
270
- // rowMajor: uniformRowMajor[i]
271
- });
272
275
  }
273
276
 
274
277
  uniformBlocks.push(blockInfo);
@@ -314,13 +317,11 @@ function parseUniformName(name: string): {name: string; length: number; isArray:
314
317
  // if array name then clean the array brackets
315
318
  const UNIFORM_NAME_REGEXP = /([^[]*)(\[[0-9]+\])?/;
316
319
  const matches = UNIFORM_NAME_REGEXP.exec(name);
317
- if (!matches || matches.length < 2) {
318
- throw new Error(`Failed to parse GLSL uniform name ${name}`);
319
- }
320
-
320
+ const uniformName = assertDefined(matches?.[1], `Failed to parse GLSL uniform name ${name}`);
321
321
  return {
322
- name: matches[1],
323
- length: matches[2] ? 1 : 0,
324
- isArray: Boolean(matches[2])
322
+ name: uniformName,
323
+ // TODO - is this a bug, shouldn't we return the value?
324
+ length: matches?.[2] ? 1 : 0,
325
+ isArray: Boolean(matches?.[2])
325
326
  };
326
327
  }
@@ -2,7 +2,7 @@
2
2
  // SPDX-License-Identifier: MIT
3
3
  // Copyright (c) vis.gl contributors
4
4
 
5
- import type {CompilerMessage} from '@luma.gl/core';
5
+ import {type CompilerMessage} from '@luma.gl/core';
6
6
 
7
7
  /**
8
8
  * Parse a WebGL-format GLSL compilation log into an array of WebGPU style message records.
@@ -20,21 +20,43 @@ export function parseShaderCompilerLog(errLog: string): readonly CompilerMessage
20
20
  continue; // eslint-disable-line no-continue
21
21
  }
22
22
 
23
+ const lineWithTrimmedWhitespace = line.trim();
24
+
23
25
  const segments: string[] = line.split(':');
26
+ const trimmedMessageType = segments[0]?.trim();
24
27
 
25
28
  // Check for messages with no line information `ERROR: unsupported shader version`
26
29
  if (segments.length === 2) {
27
30
  const [messageType, message] = segments;
31
+ if (!messageType || !message) {
32
+ messages.push({
33
+ message: lineWithTrimmedWhitespace,
34
+ type: getMessageType(trimmedMessageType || 'info'),
35
+ lineNum: 0,
36
+ linePos: 0
37
+ });
38
+ continue; // eslint-disable-line no-continue
39
+ }
28
40
  messages.push({
29
41
  message: message.trim(),
30
42
  type: getMessageType(messageType),
31
43
  lineNum: 0,
32
44
  linePos: 0
33
45
  });
46
+
34
47
  continue; // eslint-disable-line no-continue
35
48
  }
36
49
 
37
50
  const [messageType, linePosition, lineNumber, ...rest] = segments;
51
+ if (!messageType || !linePosition || !lineNumber) {
52
+ messages.push({
53
+ message: segments.slice(1).join(':').trim() || lineWithTrimmedWhitespace,
54
+ type: getMessageType(trimmedMessageType || 'info'),
55
+ lineNum: 0,
56
+ linePos: 0
57
+ });
58
+ continue; // eslint-disable-line no-continue
59
+ }
38
60
 
39
61
  let lineNum = parseInt(lineNumber, 10);
40
62
  if (isNaN(lineNum)) {
@@ -56,8 +56,12 @@ export class WEBGLBuffer extends Buffer {
56
56
  override destroy(): void {
57
57
  if (!this.destroyed && this.handle) {
58
58
  this.removeStats();
59
- this.trackDeallocatedMemory();
60
- this.gl.deleteBuffer(this.handle);
59
+ if (!this.props.handle) {
60
+ this.trackDeallocatedMemory();
61
+ this.gl.deleteBuffer(this.handle);
62
+ } else {
63
+ this.trackDeallocatedReferencedMemory('Buffer');
64
+ }
61
65
  this.destroyed = true;
62
66
  // @ts-expect-error
63
67
  this.handle = null;
@@ -81,7 +85,11 @@ export class WEBGLBuffer extends Buffer {
81
85
  this.byteLength = byteLength;
82
86
 
83
87
  this._setDebugData(data, byteOffset, byteLength);
84
- this.trackAllocatedMemory(byteLength);
88
+ if (!this.props.handle) {
89
+ this.trackAllocatedMemory(byteLength);
90
+ } else {
91
+ this.trackReferencedMemory(byteLength, 'Buffer');
92
+ }
85
93
  }
86
94
 
87
95
  // Allocate a GPU buffer of specified size.
@@ -107,7 +115,11 @@ export class WEBGLBuffer extends Buffer {
107
115
  this.byteLength = byteLength;
108
116
 
109
117
  this._setDebugData(null, 0, byteLength);
110
- this.trackAllocatedMemory(byteLength);
118
+ if (!this.props.handle) {
119
+ this.trackAllocatedMemory(byteLength);
120
+ } else {
121
+ this.trackReferencedMemory(byteLength, 'Buffer');
122
+ }
111
123
 
112
124
  return this;
113
125
  }
@@ -2,23 +2,20 @@
2
2
  // SPDX-License-Identifier: MIT
3
3
  // Copyright (c) vis.gl contributors
4
4
 
5
- import type {
6
- CopyBufferToBufferOptions,
7
- CopyBufferToTextureOptions,
8
- CopyTextureToBufferOptions,
9
- CopyTextureToTextureOptions
10
- // ClearTextureOptions,
11
- // TextureReadOptions
12
- } from '@luma.gl/core';
13
- import {CommandBuffer, Texture, Framebuffer} from '@luma.gl/core';
14
5
  import {
15
- GL,
16
- GLTextureTarget,
17
- GLTextureCubeMapTarget
18
- // GLTexelDataFormat,
19
- // GLPixelType,
20
- // GLDataType
21
- } from '@luma.gl/constants';
6
+ type CommandBufferProps,
7
+ type CopyBufferToBufferOptions,
8
+ type CopyBufferToTextureOptions,
9
+ type CopyTextureToBufferOptions,
10
+ type CopyTextureToTextureOptions,
11
+ // type ClearTextureOptions,
12
+ // type TextureReadOptions
13
+ CommandBuffer,
14
+ Texture,
15
+ Framebuffer,
16
+ assertDefined
17
+ } from '@luma.gl/core';
18
+ import {GL, type GLTextureTarget, type GLTextureCubeMapTarget} from '@luma.gl/constants';
22
19
 
23
20
  import {WebGLDevice} from '../webgl-device';
24
21
  import {WEBGLBuffer} from './webgl-buffer';
@@ -69,8 +66,8 @@ export class WEBGLCommandBuffer extends CommandBuffer {
69
66
  readonly handle = null;
70
67
  commands: Command[] = [];
71
68
 
72
- constructor(device: WebGLDevice) {
73
- super(device, {});
69
+ constructor(device: WebGLDevice, props: CommandBufferProps = {}) {
70
+ super(device, props);
74
71
  this.device = device;
75
72
  }
76
73
 
@@ -145,7 +142,7 @@ function _copyTextureToBuffer(device: WebGLDevice, options: CopyTextureToBufferO
145
142
  height = options.sourceTexture.height,
146
143
  depthOrArrayLayers = 0,
147
144
  /** Defines the origin of the copy - the minimum corner of the texture sub-region to copy to/from. */
148
- origin = [0, 0],
145
+ origin = [0, 0, 0],
149
146
 
150
147
  /** Destination buffer */
151
148
  destinationBuffer,
@@ -181,9 +178,9 @@ function _copyTextureToBuffer(device: WebGLDevice, options: CopyTextureToBufferO
181
178
  const webglBuffer = destinationBuffer as WEBGLBuffer;
182
179
  const sourceWidth = width || framebuffer.width;
183
180
  const sourceHeight = height || framebuffer.height;
184
- const sourceParams = getTextureFormatWebGL(
185
- framebuffer.colorAttachments[0].texture.props.format
186
- );
181
+ const colorAttachment0 = assertDefined(framebuffer.colorAttachments[0]);
182
+
183
+ const sourceParams = getTextureFormatWebGL(colorAttachment0.texture.props.format);
187
184
  const sourceFormat = sourceParams.format;
188
185
  const sourceType = sourceParams.type;
189
186
 
@@ -256,7 +253,7 @@ function _copyTextureToTexture(device: WebGLDevice, options: CopyTextureToTextur
256
253
  origin = [0, 0],
257
254
 
258
255
  /** Defines the origin of the copy - the minimum corner of the texture sub-region to copy to. */
259
- destinationOrigin = [0, 0],
256
+ destinationOrigin = [0, 0, 0],
260
257
 
261
258
  /** Texture to copy to/from. */
262
259
  destinationTexture
@@ -275,7 +272,7 @@ function _copyTextureToTexture(device: WebGLDevice, options: CopyTextureToTextur
275
272
  } = options;
276
273
 
277
274
  const {framebuffer, destroyFramebuffer} = getFramebuffer(sourceTexture);
278
- const [sourceX, sourceY] = origin;
275
+ const [sourceX = 0, sourceY = 0] = origin;
279
276
  const [destinationX, destinationY, destinationZ] = destinationOrigin;
280
277
 
281
278
  // @ts-expect-error native bindFramebuffer is overridden by our state tracker