@luma.gl/webgl 9.2.6 → 9.3.0-alpha.11

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 (247) hide show
  1. package/dist/adapter/converters/device-parameters.d.ts +1 -1
  2. package/dist/adapter/converters/device-parameters.d.ts.map +1 -1
  3. package/dist/adapter/converters/device-parameters.js +4 -1
  4. package/dist/adapter/converters/device-parameters.js.map +1 -1
  5. package/dist/adapter/converters/sampler-parameters.d.ts +1 -1
  6. package/dist/adapter/converters/sampler-parameters.d.ts.map +1 -1
  7. package/dist/adapter/converters/sampler-parameters.js +1 -1
  8. package/dist/adapter/converters/sampler-parameters.js.map +1 -1
  9. package/dist/adapter/converters/shader-formats.d.ts +1 -64
  10. package/dist/adapter/converters/shader-formats.d.ts.map +1 -1
  11. package/dist/adapter/converters/shader-formats.js +1 -64
  12. package/dist/adapter/converters/shader-formats.js.map +1 -1
  13. package/dist/adapter/converters/webgl-shadertypes.d.ts +1 -3
  14. package/dist/adapter/converters/webgl-shadertypes.d.ts.map +1 -1
  15. package/dist/adapter/converters/webgl-shadertypes.js +2 -7
  16. package/dist/adapter/converters/webgl-shadertypes.js.map +1 -1
  17. package/dist/adapter/converters/webgl-texture-table.d.ts +8 -4
  18. package/dist/adapter/converters/webgl-texture-table.d.ts.map +1 -1
  19. package/dist/adapter/converters/webgl-texture-table.js +125 -61
  20. package/dist/adapter/converters/webgl-texture-table.js.map +1 -1
  21. package/dist/adapter/converters/webgl-vertex-formats.d.ts +1 -1
  22. package/dist/adapter/converters/webgl-vertex-formats.d.ts.map +1 -1
  23. package/dist/adapter/converters/webgl-vertex-formats.js +4 -4
  24. package/dist/adapter/converters/webgl-vertex-formats.js.map +1 -1
  25. package/dist/adapter/device-helpers/webgl-device-features.d.ts +1 -1
  26. package/dist/adapter/device-helpers/webgl-device-features.d.ts.map +1 -1
  27. package/dist/adapter/device-helpers/webgl-device-features.js +1 -2
  28. package/dist/adapter/device-helpers/webgl-device-features.js.map +1 -1
  29. package/dist/adapter/device-helpers/webgl-device-info.d.ts +1 -1
  30. package/dist/adapter/device-helpers/webgl-device-info.d.ts.map +1 -1
  31. package/dist/adapter/device-helpers/webgl-device-info.js +6 -1
  32. package/dist/adapter/device-helpers/webgl-device-info.js.map +1 -1
  33. package/dist/adapter/device-helpers/webgl-device-limits.d.ts +1 -1
  34. package/dist/adapter/device-helpers/webgl-device-limits.d.ts.map +1 -1
  35. package/dist/adapter/device-helpers/webgl-device-limits.js +2 -2
  36. package/dist/adapter/device-helpers/webgl-device-limits.js.map +1 -1
  37. package/dist/adapter/helpers/format-utils.d.ts +1 -1
  38. package/dist/adapter/helpers/format-utils.d.ts.map +1 -1
  39. package/dist/adapter/helpers/format-utils.js +1 -1
  40. package/dist/adapter/helpers/format-utils.js.map +1 -1
  41. package/dist/adapter/helpers/get-shader-layout-from-glsl.js +36 -22
  42. package/dist/adapter/helpers/get-shader-layout-from-glsl.js.map +1 -1
  43. package/dist/adapter/helpers/parse-shader-compiler-log.d.ts +1 -1
  44. package/dist/adapter/helpers/parse-shader-compiler-log.d.ts.map +1 -1
  45. package/dist/adapter/helpers/parse-shader-compiler-log.js +22 -2
  46. package/dist/adapter/helpers/parse-shader-compiler-log.js.map +1 -1
  47. package/dist/adapter/helpers/set-uniform.d.ts +1 -1
  48. package/dist/adapter/helpers/set-uniform.d.ts.map +1 -1
  49. package/dist/adapter/helpers/set-uniform.js +2 -2
  50. package/dist/adapter/helpers/set-uniform.js.map +1 -1
  51. package/dist/adapter/helpers/webgl-texture-utils.d.ts +1 -1
  52. package/dist/adapter/helpers/webgl-texture-utils.d.ts.map +1 -1
  53. package/dist/adapter/helpers/webgl-texture-utils.js +9 -9
  54. package/dist/adapter/helpers/webgl-texture-utils.js.map +1 -1
  55. package/dist/adapter/helpers/webgl-topology-utils.d.ts +1 -1
  56. package/dist/adapter/helpers/webgl-topology-utils.d.ts.map +1 -1
  57. package/dist/adapter/helpers/webgl-topology-utils.js +3 -3
  58. package/dist/adapter/helpers/webgl-topology-utils.js.map +1 -1
  59. package/dist/adapter/resources/webgl-buffer.d.ts +1 -1
  60. package/dist/adapter/resources/webgl-buffer.d.ts.map +1 -1
  61. package/dist/adapter/resources/webgl-buffer.js +20 -5
  62. package/dist/adapter/resources/webgl-buffer.js.map +1 -1
  63. package/dist/adapter/resources/webgl-command-buffer.d.ts +7 -8
  64. package/dist/adapter/resources/webgl-command-buffer.d.ts.map +1 -1
  65. package/dist/adapter/resources/webgl-command-buffer.js +33 -43
  66. package/dist/adapter/resources/webgl-command-buffer.js.map +1 -1
  67. package/dist/adapter/resources/webgl-command-encoder.d.ts +6 -5
  68. package/dist/adapter/resources/webgl-command-encoder.d.ts.map +1 -1
  69. package/dist/adapter/resources/webgl-command-encoder.js +23 -8
  70. package/dist/adapter/resources/webgl-command-encoder.js.map +1 -1
  71. package/dist/adapter/resources/webgl-fence.d.ts +14 -0
  72. package/dist/adapter/resources/webgl-fence.d.ts.map +1 -0
  73. package/dist/adapter/resources/webgl-fence.js +49 -0
  74. package/dist/adapter/resources/webgl-fence.js.map +1 -0
  75. package/dist/adapter/resources/webgl-framebuffer.d.ts +3 -1
  76. package/dist/adapter/resources/webgl-framebuffer.d.ts.map +1 -1
  77. package/dist/adapter/resources/webgl-framebuffer.js +10 -1
  78. package/dist/adapter/resources/webgl-framebuffer.js.map +1 -1
  79. package/dist/adapter/resources/webgl-query-set.d.ts +37 -31
  80. package/dist/adapter/resources/webgl-query-set.d.ts.map +1 -1
  81. package/dist/adapter/resources/webgl-query-set.js +247 -96
  82. package/dist/adapter/resources/webgl-query-set.js.map +1 -1
  83. package/dist/adapter/resources/webgl-render-pass.d.ts +1 -1
  84. package/dist/adapter/resources/webgl-render-pass.d.ts.map +1 -1
  85. package/dist/adapter/resources/webgl-render-pass.js +28 -11
  86. package/dist/adapter/resources/webgl-render-pass.js.map +1 -1
  87. package/dist/adapter/resources/webgl-render-pipeline.d.ts +17 -21
  88. package/dist/adapter/resources/webgl-render-pipeline.d.ts.map +1 -1
  89. package/dist/adapter/resources/webgl-render-pipeline.js +94 -192
  90. package/dist/adapter/resources/webgl-render-pipeline.js.map +1 -1
  91. package/dist/adapter/resources/webgl-sampler.d.ts +1 -1
  92. package/dist/adapter/resources/webgl-sampler.d.ts.map +1 -1
  93. package/dist/adapter/resources/webgl-sampler.js +1 -1
  94. package/dist/adapter/resources/webgl-sampler.js.map +1 -1
  95. package/dist/adapter/resources/webgl-shader.d.ts +1 -1
  96. package/dist/adapter/resources/webgl-shader.d.ts.map +1 -1
  97. package/dist/adapter/resources/webgl-shader.js +15 -8
  98. package/dist/adapter/resources/webgl-shader.js.map +1 -1
  99. package/dist/adapter/resources/webgl-shared-render-pipeline.d.ts +24 -0
  100. package/dist/adapter/resources/webgl-shared-render-pipeline.d.ts.map +1 -0
  101. package/dist/adapter/resources/webgl-shared-render-pipeline.js +155 -0
  102. package/dist/adapter/resources/webgl-shared-render-pipeline.js.map +1 -0
  103. package/dist/adapter/resources/webgl-texture.d.ts +42 -4
  104. package/dist/adapter/resources/webgl-texture.d.ts.map +1 -1
  105. package/dist/adapter/resources/webgl-texture.js +289 -65
  106. package/dist/adapter/resources/webgl-texture.js.map +1 -1
  107. package/dist/adapter/resources/webgl-transform-feedback.js +6 -6
  108. package/dist/adapter/resources/webgl-transform-feedback.js.map +1 -1
  109. package/dist/adapter/resources/webgl-vertex-array.d.ts +2 -2
  110. package/dist/adapter/resources/webgl-vertex-array.d.ts.map +1 -1
  111. package/dist/adapter/resources/webgl-vertex-array.js +1 -1
  112. package/dist/adapter/resources/webgl-vertex-array.js.map +1 -1
  113. package/dist/adapter/webgl-adapter.d.ts.map +1 -1
  114. package/dist/adapter/webgl-adapter.js +22 -23
  115. package/dist/adapter/webgl-adapter.js.map +1 -1
  116. package/dist/adapter/webgl-canvas-context.d.ts +2 -2
  117. package/dist/adapter/webgl-canvas-context.d.ts.map +1 -1
  118. package/dist/adapter/webgl-canvas-context.js +16 -6
  119. package/dist/adapter/webgl-canvas-context.js.map +1 -1
  120. package/dist/adapter/webgl-device.d.ts +10 -5
  121. package/dist/adapter/webgl-device.d.ts.map +1 -1
  122. package/dist/adapter/webgl-device.js +78 -28
  123. package/dist/adapter/webgl-device.js.map +1 -1
  124. package/dist/adapter/webgl-presentation-context.d.ts +21 -0
  125. package/dist/adapter/webgl-presentation-context.d.ts.map +1 -0
  126. package/dist/adapter/webgl-presentation-context.js +64 -0
  127. package/dist/adapter/webgl-presentation-context.js.map +1 -0
  128. package/dist/constants/index.d.ts +3 -0
  129. package/dist/constants/index.d.ts.map +1 -0
  130. package/dist/constants/index.js +5 -0
  131. package/dist/constants/index.js.map +1 -0
  132. package/dist/constants/webgl-constants.d.ts +822 -0
  133. package/dist/constants/webgl-constants.d.ts.map +1 -0
  134. package/dist/constants/webgl-constants.js +928 -0
  135. package/dist/constants/webgl-constants.js.map +1 -0
  136. package/dist/constants/webgl-types.d.ts +480 -0
  137. package/dist/constants/webgl-types.d.ts.map +1 -0
  138. package/dist/constants/webgl-types.js +6 -0
  139. package/dist/constants/webgl-types.js.map +1 -0
  140. package/dist/context/debug/spector.d.ts.map +1 -1
  141. package/dist/context/debug/spector.js +4 -4
  142. package/dist/context/debug/spector.js.map +1 -1
  143. package/dist/context/debug/webgl-developer-tools.js +11 -9
  144. package/dist/context/debug/webgl-developer-tools.js.map +1 -1
  145. package/dist/context/helpers/create-browser-context.d.ts.map +1 -1
  146. package/dist/context/helpers/create-browser-context.js +46 -36
  147. package/dist/context/helpers/create-browser-context.js.map +1 -1
  148. package/dist/context/helpers/webgl-context-data.d.ts +5 -1
  149. package/dist/context/helpers/webgl-context-data.d.ts.map +1 -1
  150. package/dist/context/helpers/webgl-context-data.js +9 -10
  151. package/dist/context/helpers/webgl-context-data.js.map +1 -1
  152. package/dist/context/helpers/webgl-extensions.d.ts +1 -1
  153. package/dist/context/helpers/webgl-extensions.d.ts.map +1 -1
  154. package/dist/context/parameters/unified-parameter-api.d.ts +2 -2
  155. package/dist/context/parameters/unified-parameter-api.d.ts.map +1 -1
  156. package/dist/context/parameters/unified-parameter-api.js +2 -2
  157. package/dist/context/parameters/unified-parameter-api.js.map +1 -1
  158. package/dist/context/parameters/webgl-parameter-tables.d.ts +1 -1
  159. package/dist/context/parameters/webgl-parameter-tables.d.ts.map +1 -1
  160. package/dist/context/parameters/webgl-parameter-tables.js +1 -1
  161. package/dist/context/parameters/webgl-parameter-tables.js.map +1 -1
  162. package/dist/context/polyfills/polyfill-webgl1-extensions.js +1 -1
  163. package/dist/context/polyfills/polyfill-webgl1-extensions.js.map +1 -1
  164. package/dist/context/state-tracker/webgl-state-tracker.js +2 -2
  165. package/dist/context/state-tracker/webgl-state-tracker.js.map +1 -1
  166. package/dist/dist.dev.js +1898 -997
  167. package/dist/dist.min.js +2 -2
  168. package/dist/index.cjs +3 -5255
  169. package/dist/index.cjs.map +4 -4
  170. package/dist/index.d.ts +3 -0
  171. package/dist/index.d.ts.map +1 -1
  172. package/dist/index.js +2 -0
  173. package/dist/index.js.map +1 -1
  174. package/dist/utils/fill-array.js +1 -1
  175. package/dist/utils/fill-array.js.map +1 -1
  176. package/dist/webgl-constants.d.ts +2 -0
  177. package/dist/webgl-constants.d.ts.map +1 -0
  178. package/dist/webgl-constants.js +5 -0
  179. package/dist/webgl-constants.js.map +1 -0
  180. package/dist/webgl-types.d.ts +2 -0
  181. package/dist/webgl-types.d.ts.map +1 -0
  182. package/dist/{types.js → webgl-types.js} +1 -1
  183. package/dist/webgl-types.js.map +1 -0
  184. package/package.json +19 -5
  185. package/src/adapter/converters/device-parameters.ts +6 -2
  186. package/src/adapter/converters/sampler-parameters.ts +1 -1
  187. package/src/adapter/converters/shader-formats.ts +1 -66
  188. package/src/adapter/converters/webgl-shadertypes.ts +2 -10
  189. package/src/adapter/converters/webgl-texture-table.ts +160 -68
  190. package/src/adapter/converters/webgl-vertex-formats.ts +4 -4
  191. package/src/adapter/device-helpers/webgl-device-features.ts +2 -3
  192. package/src/adapter/device-helpers/webgl-device-info.ts +7 -1
  193. package/src/adapter/device-helpers/webgl-device-limits.ts +2 -2
  194. package/src/adapter/helpers/format-utils.ts +1 -1
  195. package/src/adapter/helpers/get-shader-layout-from-glsl.ts +44 -24
  196. package/src/adapter/helpers/parse-shader-compiler-log.ts +25 -3
  197. package/src/adapter/helpers/set-uniform.ts +2 -2
  198. package/src/adapter/helpers/webgl-texture-utils.ts +9 -9
  199. package/src/adapter/helpers/webgl-topology-utils.ts +3 -3
  200. package/src/adapter/resources/webgl-buffer.ts +17 -5
  201. package/src/adapter/resources/webgl-command-buffer.ts +48 -52
  202. package/src/adapter/resources/webgl-command-encoder.ts +28 -11
  203. package/src/adapter/resources/webgl-fence.ts +55 -0
  204. package/src/adapter/resources/webgl-framebuffer.ts +12 -1
  205. package/src/adapter/resources/webgl-query-set.ts +295 -101
  206. package/src/adapter/resources/webgl-render-pass.ts +30 -13
  207. package/src/adapter/resources/webgl-render-pipeline.ts +131 -227
  208. package/src/adapter/resources/webgl-sampler.ts +1 -1
  209. package/src/adapter/resources/webgl-shader.ts +15 -8
  210. package/src/adapter/resources/webgl-shared-render-pipeline.ts +211 -0
  211. package/src/adapter/resources/webgl-texture.ts +458 -84
  212. package/src/adapter/resources/webgl-transform-feedback.ts +6 -6
  213. package/src/adapter/resources/webgl-vertex-array.ts +1 -1
  214. package/src/adapter/webgl-adapter.ts +26 -24
  215. package/src/adapter/webgl-canvas-context.ts +19 -8
  216. package/src/adapter/webgl-device.ts +94 -35
  217. package/src/adapter/webgl-presentation-context.ts +93 -0
  218. package/src/constants/index.d.ts.map +1 -0
  219. package/src/constants/index.js.map +1 -0
  220. package/src/constants/index.ts +31 -0
  221. package/src/constants/webgl-constants.d.ts.map +1 -0
  222. package/src/constants/webgl-constants.js.map +1 -0
  223. package/src/constants/webgl-constants.ts +1051 -0
  224. package/src/constants/webgl-types.d.ts.map +1 -0
  225. package/src/constants/webgl-types.js.map +1 -0
  226. package/src/constants/webgl-types.ts +813 -0
  227. package/src/context/debug/spector.ts +4 -4
  228. package/src/context/debug/webgl-developer-tools.ts +20 -9
  229. package/src/context/helpers/create-browser-context.ts +54 -43
  230. package/src/context/helpers/webgl-context-data.ts +17 -11
  231. package/src/context/helpers/webgl-extensions.ts +1 -1
  232. package/src/context/parameters/unified-parameter-api.ts +3 -3
  233. package/src/context/parameters/webgl-parameter-tables.ts +1 -1
  234. package/src/context/polyfills/polyfill-webgl1-extensions.ts +1 -1
  235. package/src/context/state-tracker/webgl-state-tracker.ts +2 -2
  236. package/src/index.ts +27 -0
  237. package/src/utils/fill-array.ts +1 -1
  238. package/src/webgl-constants.d.ts.map +1 -0
  239. package/src/webgl-constants.js.map +1 -0
  240. package/src/webgl-constants.ts +5 -0
  241. package/src/webgl-types.d.ts.map +1 -0
  242. package/src/webgl-types.js.map +1 -0
  243. package/src/webgl-types.ts +29 -0
  244. package/dist/types.d.ts +0 -11
  245. package/dist/types.d.ts.map +0 -1
  246. package/dist/types.js.map +0 -1
  247. package/src/types.ts +0 -14
@@ -2,33 +2,43 @@
2
2
  // SPDX-License-Identifier: MIT
3
3
  // Copyright (c) vis.gl contributors
4
4
 
5
- import type {
6
- Device,
7
- TextureProps,
8
- TextureViewProps,
9
- Sampler,
10
- SamplerProps,
11
- CopyExternalImageOptions,
12
- CopyImageDataOptions,
13
- TypedArray
5
+ // @ts-nocheck
6
+
7
+ import {
8
+ type Device,
9
+ type TextureProps,
10
+ type TextureViewProps,
11
+ type Sampler,
12
+ type SamplerProps,
13
+ type CopyExternalImageOptions,
14
+ type TextureReadOptions,
15
+ type TextureWriteOptions,
16
+ type TextureFormat,
17
+ Buffer,
18
+ getTypedArrayConstructor,
19
+ Texture,
20
+ log
14
21
  } from '@luma.gl/core';
15
- import {Texture, log} from '@luma.gl/core';
22
+
16
23
  import {
24
+ GLSamplerParameters,
25
+ GLValueParameters,
17
26
  GL,
18
27
  GLTextureTarget,
19
28
  GLTextureCubeMapTarget,
20
29
  GLTexelDataFormat,
21
- GLPixelType,
22
- // GLDataType,
23
- GLSamplerParameters,
24
- GLValueParameters
25
- } from '@luma.gl/constants';
30
+ GLPixelType
31
+ } from '@luma.gl/webgl/constants';
32
+
26
33
  import {getTextureFormatWebGL} from '../converters/webgl-texture-table';
27
34
  import {convertSamplerParametersToWebGL} from '../converters/sampler-parameters';
28
35
  import {withGLParameters} from '../../context/state-tracker/with-parameters';
29
36
  import {WebGLDevice} from '../webgl-device';
37
+ import {WEBGLBuffer} from './webgl-buffer';
38
+ import {WEBGLFramebuffer} from './webgl-framebuffer';
30
39
  import {WEBGLSampler} from './webgl-sampler';
31
40
  import {WEBGLTextureView} from './webgl-texture-view';
41
+ import {convertGLDataTypeToDataType} from '../converters/shader-formats';
32
42
 
33
43
  /**
34
44
  * WebGL... the texture API from hell... hopefully made simpler
@@ -65,9 +75,14 @@ export class WEBGLTexture extends Texture {
65
75
  // state
66
76
  /** Texture binding slot - TODO - move to texture view? */
67
77
  _textureUnit: number = 0;
78
+ /** Cached framebuffer reused for color texture readback. */
79
+ _framebuffer: WEBGLFramebuffer | null = null;
80
+ /** Cache key for the currently attached readback subresource `${mipLevel}:${layer}`. */
81
+ _framebufferAttachmentKey: string | null = null;
68
82
 
69
83
  constructor(device: Device, props: TextureProps) {
70
- super(device, props);
84
+ // const byteAlignment = this._getRowByteAlignment(props.format, props.width);
85
+ super(device, props, {byteAlignment: 1});
71
86
 
72
87
  this.device = device as WebGLDevice;
73
88
  this.gl = this.device.gl;
@@ -92,23 +107,31 @@ export class WEBGLTexture extends Texture {
92
107
  */
93
108
  this.gl.bindTexture(this.glTarget, this.handle);
94
109
  const {dimension, width, height, depth, mipLevels, glTarget, glInternalFormat} = this;
95
- switch (dimension) {
96
- case '2d':
97
- case 'cube':
98
- this.gl.texStorage2D(glTarget, mipLevels, glInternalFormat, width, height);
99
- break;
100
- case '2d-array':
101
- case '3d':
102
- this.gl.texStorage3D(glTarget, mipLevels, glInternalFormat, width, height, depth);
103
- break;
104
- default:
105
- throw new Error(dimension);
110
+ if (!this.compressed) {
111
+ switch (dimension) {
112
+ case '2d':
113
+ case 'cube':
114
+ this.gl.texStorage2D(glTarget, mipLevels, glInternalFormat, width, height);
115
+ break;
116
+ case '2d-array':
117
+ case '3d':
118
+ this.gl.texStorage3D(glTarget, mipLevels, glInternalFormat, width, height, depth);
119
+ break;
120
+ default:
121
+ throw new Error(dimension);
122
+ }
106
123
  }
107
124
  this.gl.bindTexture(this.glTarget, null);
108
125
 
109
126
  // Set data
110
127
  this._initializeData(props.data);
111
128
 
129
+ if (!this.props.handle) {
130
+ this.trackAllocatedMemory(this.getAllocatedByteLength(), 'Texture');
131
+ } else {
132
+ this.trackReferencedMemory(this.getAllocatedByteLength(), 'Texture');
133
+ }
134
+
112
135
  // Set texture sampler parameters
113
136
  this.setSampler(this.props.sampler);
114
137
  // @ts-ignore TODO - fix types
@@ -119,9 +142,18 @@ export class WEBGLTexture extends Texture {
119
142
 
120
143
  override destroy(): void {
121
144
  if (this.handle) {
122
- this.gl.deleteTexture(this.handle);
145
+ // Destroy any cached framebuffer
146
+ this._framebuffer?.destroy();
147
+ this._framebuffer = null;
148
+ this._framebufferAttachmentKey = null;
149
+
123
150
  this.removeStats();
124
- this.trackDeallocatedMemory('Texture');
151
+ if (!this.props.handle) {
152
+ this.gl.deleteTexture(this.handle);
153
+ this.trackDeallocatedMemory('Texture');
154
+ } else {
155
+ this.trackDeallocatedReferencedMemory('Texture');
156
+ }
125
157
  // this.handle = null;
126
158
  this.destroyed = true;
127
159
  }
@@ -138,59 +170,247 @@ export class WEBGLTexture extends Texture {
138
170
  this._setSamplerParameters(parameters);
139
171
  }
140
172
 
141
- copyImageData(options_: CopyImageDataOptions): void {
142
- const options = this._normalizeCopyImageDataOptions(options_);
173
+ copyExternalImage(options_: CopyExternalImageOptions): {width: number; height: number} {
174
+ const options = this._normalizeCopyExternalImageOptions(options_);
175
+
176
+ if (options.sourceX || options.sourceY) {
177
+ // requires copyTexSubImage2D from a framebuffer'
178
+ throw new Error('WebGL does not support sourceX/sourceY)');
179
+ }
180
+
181
+ const {glFormat, glType} = this;
182
+ const {image, depth, mipLevel, x, y, z, width, height} = options;
183
+
184
+ // WebGL cube maps specify faces by overriding target instead of using the z parameter
185
+ const glTarget = getWebGLCubeFaceTarget(this.glTarget, this.dimension, z);
186
+ const glParameters: GLValueParameters = options.flipY ? {[GL.UNPACK_FLIP_Y_WEBGL]: true} : {};
143
187
 
144
- const typedArray = options.data as TypedArray;
145
- const {width, height, depth} = this;
146
- const {mipLevel = 0, byteOffset = 0, x = 0, y = 0, z = 0} = options;
188
+ this.gl.bindTexture(this.glTarget, this.handle);
189
+
190
+ withGLParameters(this.gl, glParameters, () => {
191
+ switch (this.dimension) {
192
+ case '2d':
193
+ case 'cube':
194
+ // biome-ignore format: preserve layout
195
+ this.gl.texSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, glType, image);
196
+ break;
197
+ case '2d-array':
198
+ case '3d':
199
+ // biome-ignore format: preserve layout
200
+ this.gl.texSubImage3D(glTarget, mipLevel, x, y, z, width, height, depth, glFormat, glType, image);
201
+ break;
202
+ default:
203
+ // Can never happen in WebGL
204
+ }
205
+ });
206
+
207
+ this.gl.bindTexture(this.glTarget, null);
208
+
209
+ return {width: options.width, height: options.height};
210
+ }
211
+
212
+ override copyImageData(options_): void {
213
+ super.copyImageData(options_);
214
+ }
215
+
216
+ /**
217
+ * Reads a color texture subresource into a GPU buffer using `PIXEL_PACK_BUFFER`.
218
+ *
219
+ * @note Only first-pass color readback is supported. Unsupported formats and aspects throw
220
+ * before any WebGL calls are issued.
221
+ */
222
+ readBuffer(options: TextureReadOptions & {byteOffset?: number} = {}, buffer?: Buffer): Buffer {
223
+ if (!buffer) {
224
+ throw new Error(`${this} readBuffer requires a destination buffer`);
225
+ }
226
+ const normalizedOptions = this._getSupportedColorReadOptions(options);
227
+ const byteOffset = options.byteOffset ?? 0;
228
+ const memoryLayout = this.computeMemoryLayout(normalizedOptions);
229
+
230
+ if (buffer.byteLength < byteOffset + memoryLayout.byteLength) {
231
+ throw new Error(
232
+ `${this} readBuffer target is too small (${buffer.byteLength} < ${byteOffset + memoryLayout.byteLength})`
233
+ );
234
+ }
235
+
236
+ const webglBuffer = buffer as WEBGLBuffer;
237
+ this.gl.bindBuffer(GL.PIXEL_PACK_BUFFER, webglBuffer.handle);
238
+ try {
239
+ this._readColorTextureLayers(normalizedOptions, memoryLayout, destinationByteOffset => {
240
+ this.gl.readPixels(
241
+ normalizedOptions.x,
242
+ normalizedOptions.y,
243
+ normalizedOptions.width,
244
+ normalizedOptions.height,
245
+ this.glFormat,
246
+ this.glType,
247
+ byteOffset + destinationByteOffset
248
+ );
249
+ });
250
+ } finally {
251
+ this.gl.bindBuffer(GL.PIXEL_PACK_BUFFER, null);
252
+ }
253
+
254
+ return buffer;
255
+ }
256
+
257
+ async readDataAsync(options: TextureReadOptions = {}): Promise<ArrayBuffer> {
258
+ throw new Error(
259
+ `${this} readDataAsync is deprecated; use readBuffer() with an explicit destination buffer or DynamicTexture.readAsync()`
260
+ );
261
+ }
262
+
263
+ writeBuffer(buffer: Buffer, options_: TextureWriteOptions = {}) {
264
+ const options = this._normalizeTextureWriteOptions(options_);
265
+ const {width, height, depthOrArrayLayers, mipLevel, byteOffset, x, y, z} = options;
147
266
  const {glFormat, glType, compressed} = this;
267
+ const glTarget = getWebGLCubeFaceTarget(this.glTarget, this.dimension, z);
268
+
269
+ if (compressed) {
270
+ throw new Error('writeBuffer for compressed textures is not implemented in WebGL');
271
+ }
272
+
273
+ const {bytesPerPixel} = this.device.getTextureFormatInfo(this.format);
274
+ const unpackRowLength = bytesPerPixel ? options.bytesPerRow / bytesPerPixel : undefined;
275
+ const glParameters: GLValueParameters = {
276
+ [GL.UNPACK_ALIGNMENT]: this.byteAlignment,
277
+ ...(unpackRowLength !== undefined ? {[GL.UNPACK_ROW_LENGTH]: unpackRowLength} : {}),
278
+ [GL.UNPACK_IMAGE_HEIGHT]: options.rowsPerImage
279
+ };
280
+
281
+ this.gl.bindTexture(this.glTarget, this.handle);
282
+ this.gl.bindBuffer(GL.PIXEL_UNPACK_BUFFER, buffer.handle);
283
+
284
+ withGLParameters(this.gl, glParameters, () => {
285
+ switch (this.dimension) {
286
+ case '2d':
287
+ case 'cube':
288
+ this.gl.texSubImage2D(
289
+ glTarget,
290
+ mipLevel,
291
+ x,
292
+ y,
293
+ width,
294
+ height,
295
+ glFormat,
296
+ glType,
297
+ byteOffset
298
+ );
299
+ break;
300
+ case '2d-array':
301
+ case '3d':
302
+ this.gl.texSubImage3D(
303
+ glTarget,
304
+ mipLevel,
305
+ x,
306
+ y,
307
+ z,
308
+ width,
309
+ height,
310
+ depthOrArrayLayers,
311
+ glFormat,
312
+ glType,
313
+ byteOffset
314
+ );
315
+ break;
316
+ default:
317
+ }
318
+ });
319
+
320
+ this.gl.bindBuffer(GL.PIXEL_UNPACK_BUFFER, null);
321
+ this.gl.bindTexture(this.glTarget, null);
322
+ }
323
+
324
+ writeData(
325
+ data: ArrayBuffer | SharedArrayBuffer | ArrayBufferView,
326
+ options_: TextureWriteOptions = {}
327
+ ): void {
328
+ const options = this._normalizeTextureWriteOptions(options_);
148
329
 
149
- // Target used for face updates, but not for binding
330
+ const typedArray = ArrayBuffer.isView(data) ? data : new Uint8Array(data);
331
+ const {width, height, depthOrArrayLayers, mipLevel, x, y, z, byteOffset} = options;
332
+ const {glFormat, glType, compressed} = this;
150
333
  const glTarget = getWebGLCubeFaceTarget(this.glTarget, this.dimension, z);
151
334
 
152
335
  let unpackRowLength: number | undefined;
153
- if (!this.compressed) {
336
+ if (!compressed) {
154
337
  const {bytesPerPixel} = this.device.getTextureFormatInfo(this.format);
155
338
  if (bytesPerPixel) {
156
- if (options.bytesPerRow % bytesPerPixel !== 0) {
157
- throw new Error(
158
- `bytesPerRow (${options.bytesPerRow}) must be a multiple of bytesPerPixel (${bytesPerPixel}) for ${this.format}`
159
- );
160
- }
161
339
  unpackRowLength = options.bytesPerRow / bytesPerPixel;
162
340
  }
163
341
  }
164
342
 
165
343
  const glParameters: GLValueParameters = !this.compressed
166
344
  ? {
345
+ [GL.UNPACK_ALIGNMENT]: this.byteAlignment,
167
346
  ...(unpackRowLength !== undefined ? {[GL.UNPACK_ROW_LENGTH]: unpackRowLength} : {}),
168
347
  [GL.UNPACK_IMAGE_HEIGHT]: options.rowsPerImage
169
348
  }
170
349
  : {};
350
+ const sourceElementOffset = getWebGLTextureSourceElementOffset(typedArray, byteOffset);
351
+ const compressedData = compressed ? getArrayBufferView(typedArray, byteOffset) : typedArray;
352
+ const mipLevelSize = this._getMipLevelSize(mipLevel);
353
+ const isFullMipUpload =
354
+ x === 0 &&
355
+ y === 0 &&
356
+ z === 0 &&
357
+ width === mipLevelSize.width &&
358
+ height === mipLevelSize.height &&
359
+ depthOrArrayLayers === mipLevelSize.depthOrArrayLayers;
171
360
 
172
- this.gl.bindTexture(glTarget, this.handle);
361
+ this.gl.bindTexture(this.glTarget, this.handle);
362
+ this.gl.bindBuffer(GL.PIXEL_UNPACK_BUFFER, null);
173
363
 
174
364
  withGLParameters(this.gl, glParameters, () => {
175
365
  switch (this.dimension) {
176
366
  case '2d':
177
367
  case 'cube':
178
368
  if (compressed) {
179
- // prettier-ignore
180
- this.gl.compressedTexSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, typedArray, byteOffset); // , byteLength
369
+ if (isFullMipUpload) {
370
+ // biome-ignore format: preserve layout
371
+ this.gl.compressedTexImage2D(glTarget, mipLevel, glFormat, width, height, 0, compressedData);
372
+ } else {
373
+ // biome-ignore format: preserve layout
374
+ this.gl.compressedTexSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, compressedData);
375
+ }
181
376
  } else {
182
- // prettier-ignore
183
- this.gl.texSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, glType, typedArray, byteOffset); // , byteLength
377
+ // biome-ignore format: preserve layout
378
+ this.gl.texSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, glType, typedArray, sourceElementOffset);
184
379
  }
185
380
  break;
186
381
  case '2d-array':
187
382
  case '3d':
188
383
  if (compressed) {
189
- // prettier-ignore
190
- this.gl.compressedTexSubImage3D(glTarget, mipLevel, x, y, z, width, height, depth, glFormat, typedArray, byteOffset); // , byteLength
384
+ if (isFullMipUpload) {
385
+ // biome-ignore format: preserve layout
386
+ this.gl.compressedTexImage3D(
387
+ glTarget,
388
+ mipLevel,
389
+ glFormat,
390
+ width,
391
+ height,
392
+ depthOrArrayLayers,
393
+ 0,
394
+ compressedData
395
+ );
396
+ } else {
397
+ // biome-ignore format: preserve layout
398
+ this.gl.compressedTexSubImage3D(
399
+ glTarget,
400
+ mipLevel,
401
+ x,
402
+ y,
403
+ z,
404
+ width,
405
+ height,
406
+ depthOrArrayLayers,
407
+ glFormat,
408
+ compressedData
409
+ );
410
+ }
191
411
  } else {
192
- // prettier-ignore
193
- this.gl.texSubImage3D(glTarget, mipLevel, x, y, z, width, height, depth, glFormat, glType, typedArray, byteOffset); // , byteLength
412
+ // biome-ignore format: preserve layout
413
+ this.gl.texSubImage3D(glTarget, mipLevel, x, y, z, width, height, depthOrArrayLayers, glFormat, glType, typedArray, sourceElementOffset);
194
414
  }
195
415
  break;
196
416
  default:
@@ -198,51 +418,179 @@ export class WEBGLTexture extends Texture {
198
418
  }
199
419
  });
200
420
 
201
- this.gl.bindTexture(glTarget, null);
421
+ this.gl.bindTexture(this.glTarget, null);
202
422
  }
203
423
 
204
- copyExternalImage(options_: CopyExternalImageOptions): {width: number; height: number} {
205
- const options = this._normalizeCopyExternalImageOptions(options_);
424
+ // IMPLEMENTATION SPECIFIC
425
+
426
+ /** @todo - for now we always use 1 for maximum compatibility, we can fine tune later */
427
+ private _getRowByteAlignment(format: TextureFormat, width: number): 1 | 2 | 4 | 8 {
428
+ // For best texture data read/write performance, calculate the biggest pack/unpack alignment
429
+ // that fits with the provided texture row byte length
430
+ // Note: Any RGBA or 32 bit type will be at least 4 bytes, which should result in good performance.
431
+ // const info = this.device.getTextureFormatInfo(format);
432
+ // const rowByteLength = width * info.bytesPerPixel;
433
+ // if (rowByteLength % 8 === 0) return 8;
434
+ // if (rowByteLength % 4 === 0) return 4;
435
+ // if (rowByteLength % 2 === 0) return 2;
436
+ return 1;
437
+ }
206
438
 
207
- if (options.sourceX || options.sourceY) {
208
- // requires copyTexSubImage2D from a framebuffer'
209
- throw new Error('WebGL does not support sourceX/sourceY)');
439
+ /**
440
+ * Wraps a given texture into a framebuffer object, that can be further used
441
+ * to read data from the texture object.
442
+ */
443
+ _getFramebuffer() {
444
+ this._framebuffer ||= this.device.createFramebuffer({
445
+ id: `framebuffer-for-${this.id}`,
446
+ width: this.width,
447
+ height: this.height,
448
+ colorAttachments: [this]
449
+ });
450
+ return this._framebuffer;
451
+ }
452
+
453
+ // WEBGL SPECIFIC
454
+
455
+ override readDataSyncWebGL(options_: TextureReadOptions = {}): ArrayBuffer {
456
+ const options = this._getSupportedColorReadOptions(options_);
457
+ const memoryLayout = this.computeMemoryLayout(options);
458
+
459
+ // const formatInfo = getTextureFormatInfo(format);
460
+ // Allocate pixel array if not already available, using supplied type
461
+ const shaderType = convertGLDataTypeToDataType(this.glType);
462
+ const ArrayType = getTypedArrayConstructor(shaderType);
463
+ const targetArray = new ArrayType(memoryLayout.byteLength / ArrayType.BYTES_PER_ELEMENT) as
464
+ | Uint8Array
465
+ | Uint16Array
466
+ | Float32Array
467
+ | Int8Array
468
+ | Int16Array
469
+ | Int32Array
470
+ | Uint32Array;
471
+
472
+ this._readColorTextureLayers(options, memoryLayout, destinationByteOffset => {
473
+ const layerView = new ArrayType(
474
+ targetArray.buffer,
475
+ targetArray.byteOffset + destinationByteOffset,
476
+ memoryLayout.bytesPerImage / ArrayType.BYTES_PER_ELEMENT
477
+ );
478
+ this.gl.readPixels(
479
+ options.x,
480
+ options.y,
481
+ options.width,
482
+ options.height,
483
+ this.glFormat,
484
+ this.glType,
485
+ layerView
486
+ );
487
+ });
488
+
489
+ return targetArray.buffer as ArrayBuffer;
490
+ }
491
+
492
+ /**
493
+ * Iterates the requested mip/layer/slice range, reattaching the cached read framebuffer as
494
+ * needed before delegating the actual `readPixels()` call to the supplied callback.
495
+ */
496
+ private _readColorTextureLayers(
497
+ options: Required<TextureReadOptions>,
498
+ memoryLayout: ReturnType<Texture['computeMemoryLayout']>,
499
+ readLayer: (destinationByteOffset: number) => void
500
+ ): void {
501
+ const framebuffer = this._getFramebuffer();
502
+ const packRowLength = memoryLayout.bytesPerRow / memoryLayout.bytesPerPixel;
503
+ const glParameters: GLValueParameters = {
504
+ [GL.PACK_ALIGNMENT]: this.byteAlignment,
505
+ ...(packRowLength !== options.width ? {[GL.PACK_ROW_LENGTH]: packRowLength} : {})
506
+ };
507
+
508
+ // Note: luma.gl overrides bindFramebuffer so that we can reliably restore the previous framebuffer.
509
+ const prevReadBuffer = this.gl.getParameter(GL.READ_BUFFER) as GL;
510
+ const prevHandle = this.gl.bindFramebuffer(
511
+ GL.FRAMEBUFFER,
512
+ framebuffer.handle
513
+ ) as unknown as WebGLFramebuffer | null;
514
+
515
+ try {
516
+ this.gl.readBuffer(GL.COLOR_ATTACHMENT0);
517
+ withGLParameters(this.gl, glParameters, () => {
518
+ for (let layerIndex = 0; layerIndex < options.depthOrArrayLayers; layerIndex++) {
519
+ this._attachReadSubresource(framebuffer, options.mipLevel, options.z + layerIndex);
520
+ readLayer(layerIndex * memoryLayout.bytesPerImage);
521
+ }
522
+ });
523
+ } finally {
524
+ this.gl.bindFramebuffer(GL.FRAMEBUFFER, prevHandle || null);
525
+ this.gl.readBuffer(prevReadBuffer);
210
526
  }
527
+ }
211
528
 
212
- const {glFormat, glType} = this;
213
- const {image, depth, mipLevel, x, y, z, width, height} = options;
529
+ /**
530
+ * Attaches a single color subresource to the cached read framebuffer.
531
+ *
532
+ * @note Repeated attachments of the same `(mipLevel, layer)` tuple are skipped.
533
+ */
534
+ private _attachReadSubresource(
535
+ framebuffer: WEBGLFramebuffer,
536
+ mipLevel: number,
537
+ layer: number
538
+ ): void {
539
+ const attachmentKey = `${mipLevel}:${layer}`;
540
+ if (this._framebufferAttachmentKey === attachmentKey) {
541
+ return;
542
+ }
214
543
 
215
- // WebGL cube maps specify faces by overriding target instead of using the depth parameter
216
- const glTarget = getWebGLCubeFaceTarget(this.glTarget, this.dimension, depth);
217
- const glParameters: GLValueParameters = options.flipY ? {[GL.UNPACK_FLIP_Y_WEBGL]: true} : {};
544
+ switch (this.dimension) {
545
+ case '2d':
546
+ this.gl.framebufferTexture2D(
547
+ GL.FRAMEBUFFER,
548
+ GL.COLOR_ATTACHMENT0,
549
+ GL.TEXTURE_2D,
550
+ this.handle,
551
+ mipLevel
552
+ );
553
+ break;
218
554
 
219
- this.gl.bindTexture(this.glTarget, this.handle);
555
+ case 'cube':
556
+ this.gl.framebufferTexture2D(
557
+ GL.FRAMEBUFFER,
558
+ GL.COLOR_ATTACHMENT0,
559
+ getWebGLCubeFaceTarget(this.glTarget, this.dimension, layer),
560
+ this.handle,
561
+ mipLevel
562
+ );
563
+ break;
220
564
 
221
- withGLParameters(this.gl, glParameters, () => {
222
- switch (this.dimension) {
223
- case '2d':
224
- case 'cube':
225
- // prettier-ignore
226
- this.gl.texSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, glType, image);
227
- break;
228
- case '2d-array':
229
- case '3d':
230
- // prettier-ignore
231
- this.gl.texSubImage3D(glTarget, mipLevel, x, y, z, width, height, depth, glFormat, glType, image);
232
- break;
233
- default:
234
- // Can never happen in WebGL
235
- }
236
- });
565
+ case '2d-array':
566
+ case '3d':
567
+ this.gl.framebufferTextureLayer(
568
+ GL.FRAMEBUFFER,
569
+ GL.COLOR_ATTACHMENT0,
570
+ this.handle,
571
+ mipLevel,
572
+ layer
573
+ );
574
+ break;
237
575
 
238
- this.gl.bindTexture(this.glTarget, null);
576
+ default:
577
+ throw new Error(`${this} color readback does not support ${this.dimension} textures`);
578
+ }
239
579
 
240
- return {width: options.width, height: options.height};
241
- }
580
+ if (this.device.props.debug) {
581
+ const status = Number(this.gl.checkFramebufferStatus(GL.FRAMEBUFFER));
582
+ if (status !== Number(GL.FRAMEBUFFER_COMPLETE)) {
583
+ throw new Error(`${framebuffer} incomplete for ${this} readback (${status})`);
584
+ }
585
+ }
242
586
 
243
- // WEBGL SPECIFIC
587
+ this._framebufferAttachmentKey = attachmentKey;
588
+ }
244
589
 
245
- generateMipmapsWebGL(options?: {force?: boolean}): void {
590
+ /**
591
+ * @note - this is used by the DynamicTexture class to generate mipmaps on WebGL
592
+ */
593
+ override generateMipmapsWebGL(options?: {force?: boolean}): void {
246
594
  const isFilterableAndRenderable =
247
595
  this.device.isTextureFormatRenderable(this.props.format) &&
248
596
  this.device.isTextureFormatFilterable(this.props.format);
@@ -312,6 +660,7 @@ export class WEBGLTexture extends Texture {
312
660
 
313
661
  this.gl.bindTexture(this.glTarget, null);
314
662
  }
663
+
315
664
  _getActiveUnit(): number {
316
665
  return this.gl.getParameter(GL.ACTIVE_TEXTURE) - GL.TEXTURE0;
317
666
  }
@@ -342,13 +691,38 @@ export class WEBGLTexture extends Texture {
342
691
  }
343
692
  }
344
693
 
694
+ function getArrayBufferView(typedArray: ArrayBufferView, byteOffset = 0): ArrayBufferView {
695
+ if (!byteOffset) {
696
+ return typedArray;
697
+ }
698
+
699
+ return new typedArray.constructor(
700
+ typedArray.buffer,
701
+ typedArray.byteOffset + byteOffset,
702
+ (typedArray.byteLength - byteOffset) / typedArray.BYTES_PER_ELEMENT
703
+ ) as ArrayBufferView;
704
+ }
705
+
706
+ function getWebGLTextureSourceElementOffset(
707
+ typedArray: ArrayBufferView,
708
+ byteOffset: number
709
+ ): number {
710
+ if (byteOffset % typedArray.BYTES_PER_ELEMENT !== 0) {
711
+ throw new Error(
712
+ `Texture byteOffset ${byteOffset} must align to typed array element size ${typedArray.BYTES_PER_ELEMENT}`
713
+ );
714
+ }
715
+
716
+ return byteOffset / typedArray.BYTES_PER_ELEMENT;
717
+ }
718
+
345
719
  // INTERNAL HELPERS
346
720
 
347
721
  /** Convert a WebGPU style texture constant to a WebGL style texture constant */
348
722
  export function getWebGLTextureTarget(
349
723
  dimension: '1d' | '2d' | '2d-array' | 'cube' | 'cube-array' | '3d'
350
724
  ): GLTextureTarget {
351
- // prettier-ignore
725
+ // biome-ignore format: preserve layout
352
726
  switch (dimension) {
353
727
  case '1d': break; // not supported in any WebGL version
354
728
  case '2d': return GL.TEXTURE_2D; // supported in WebGL1