@luma.gl/core 9.2.5 → 9.3.0-alpha.2

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 (74) hide show
  1. package/dist/adapter/canvas-context.d.ts +22 -3
  2. package/dist/adapter/canvas-context.d.ts.map +1 -1
  3. package/dist/adapter/canvas-context.js +39 -8
  4. package/dist/adapter/canvas-context.js.map +1 -1
  5. package/dist/adapter/device.d.ts +5 -5
  6. package/dist/adapter/device.d.ts.map +1 -1
  7. package/dist/adapter/device.js +17 -2
  8. package/dist/adapter/device.js.map +1 -1
  9. package/dist/adapter/luma.js +1 -1
  10. package/dist/adapter/luma.js.map +1 -1
  11. package/dist/adapter/resources/buffer.d.ts +4 -4
  12. package/dist/adapter/resources/buffer.d.ts.map +1 -1
  13. package/dist/adapter/resources/buffer.js +4 -1
  14. package/dist/adapter/resources/buffer.js.map +1 -1
  15. package/dist/adapter/resources/fence.d.ts +16 -0
  16. package/dist/adapter/resources/fence.d.ts.map +1 -0
  17. package/dist/adapter/resources/fence.js +15 -0
  18. package/dist/adapter/resources/fence.js.map +1 -0
  19. package/dist/adapter/resources/framebuffer.d.ts.map +1 -1
  20. package/dist/adapter/resources/framebuffer.js +6 -1
  21. package/dist/adapter/resources/framebuffer.js.map +1 -1
  22. package/dist/adapter/resources/resource.d.ts +5 -0
  23. package/dist/adapter/resources/resource.d.ts.map +1 -1
  24. package/dist/adapter/resources/resource.js +3 -0
  25. package/dist/adapter/resources/resource.js.map +1 -1
  26. package/dist/adapter/resources/texture.d.ts +97 -24
  27. package/dist/adapter/resources/texture.d.ts.map +1 -1
  28. package/dist/adapter/resources/texture.js +116 -10
  29. package/dist/adapter/resources/texture.js.map +1 -1
  30. package/dist/dist.dev.js +382 -105
  31. package/dist/dist.min.js +6 -6
  32. package/dist/index.cjs +371 -102
  33. package/dist/index.cjs.map +4 -4
  34. package/dist/index.d.ts +5 -2
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +4 -0
  37. package/dist/index.js.map +1 -1
  38. package/dist/portable/uniform-buffer-layout.d.ts +13 -4
  39. package/dist/portable/uniform-buffer-layout.d.ts.map +1 -1
  40. package/dist/portable/uniform-buffer-layout.js +88 -55
  41. package/dist/portable/uniform-buffer-layout.js.map +1 -1
  42. package/dist/shadertypes/data-types/decode-data-types.d.ts.map +1 -1
  43. package/dist/shadertypes/data-types/decode-data-types.js +2 -1
  44. package/dist/shadertypes/data-types/decode-data-types.js.map +1 -1
  45. package/dist/shadertypes/data-types/shader-types.d.ts +5 -7
  46. package/dist/shadertypes/data-types/shader-types.d.ts.map +1 -1
  47. package/dist/shadertypes/textures/texture-format-decoder.d.ts +25 -8
  48. package/dist/shadertypes/textures/texture-format-decoder.d.ts.map +1 -1
  49. package/dist/shadertypes/textures/texture-format-decoder.js +58 -32
  50. package/dist/shadertypes/textures/texture-format-decoder.js.map +1 -1
  51. package/dist/shadertypes/textures/texture-formats.d.ts +43 -16
  52. package/dist/shadertypes/textures/texture-formats.d.ts.map +1 -1
  53. package/dist/shadertypes/textures/texture-formats.js.map +1 -1
  54. package/dist/shadertypes/textures/texture-layout.d.ts +5 -0
  55. package/dist/shadertypes/textures/texture-layout.d.ts.map +1 -0
  56. package/dist/shadertypes/textures/texture-layout.js +41 -0
  57. package/dist/shadertypes/textures/texture-layout.js.map +1 -0
  58. package/package.json +2 -2
  59. package/src/adapter/canvas-context.ts +47 -13
  60. package/src/adapter/device.ts +27 -5
  61. package/src/adapter/resources/buffer.ts +6 -4
  62. package/src/adapter/resources/command-buffer.ts +1 -1
  63. package/src/adapter/resources/command-encoder.ts +2 -2
  64. package/src/adapter/resources/fence.ts +30 -0
  65. package/src/adapter/resources/framebuffer.ts +6 -1
  66. package/src/adapter/resources/resource.ts +5 -0
  67. package/src/adapter/resources/texture.ts +174 -26
  68. package/src/index.ts +11 -2
  69. package/src/portable/uniform-buffer-layout.ts +122 -63
  70. package/src/shadertypes/data-types/decode-data-types.ts +2 -1
  71. package/src/shadertypes/data-types/shader-types.ts +14 -7
  72. package/src/shadertypes/textures/texture-format-decoder.ts +95 -40
  73. package/src/shadertypes/textures/texture-formats.ts +54 -15
  74. package/src/shadertypes/textures/texture-layout.ts +60 -0
@@ -9,77 +9,132 @@ import type {
9
9
  TextureFormatCompressed,
10
10
  TextureFormatInfo,
11
11
  TextureFormatCapabilities,
12
- TextureFormatColor
12
+ TextureFormatColor,
13
+ TextureMemoryLayout,
14
+ TextureFormatDepthStencil
13
15
  } from './texture-formats';
14
16
  import {getTextureFormatDefinition} from './texture-format-table';
15
17
 
18
+ const RGB_FORMAT_REGEX = /^(r|rg|rgb|rgba|bgra)([0-9]*)([a-z]*)(-srgb)?(-webgl)?$/;
19
+ const COLOR_FORMAT_PREFIXES = ['rgb', 'rgba', 'bgra'];
20
+ const DEPTH_FORMAT_PREFIXES = ['depth', 'stencil'];
16
21
  // prettier-ignore
17
22
  const COMPRESSED_TEXTURE_FORMAT_PREFIXES = [
18
23
  'bc1', 'bc2', 'bc3', 'bc4', 'bc5', 'bc6', 'bc7', 'etc1', 'etc2', 'eac', 'atc', 'astc', 'pvrtc'
19
24
  ];
20
25
 
21
- const RGB_FORMAT_REGEX = /^(r|rg|rgb|rgba|bgra)([0-9]*)([a-z]*)(-srgb)?(-webgl)?$/;
22
-
26
+ // HELPERS - MEMORY LAYOUT
27
+
28
+ /** Options to calculate a texture layout */
29
+ export type TextureMemoryLayoutOptions = {
30
+ /** Number of bytes per pixel */
31
+ format: TextureFormat;
32
+ /** Width of the texture in pixels */
33
+ width: number;
34
+ /** Height of the texture in pixels */
35
+ height: number;
36
+ /** Number of images in the texture */
37
+ depth: number;
38
+ /** Alignment of each row */
39
+ byteAlignment: number;
40
+ };
41
+
42
+ /** Class that helps applications work with texture formats */
23
43
  export class TextureFormatDecoder {
24
- /** Returns information about a texture format, e.g. attatchment type, components, byte length and flags (integer, signed, normalized) */
25
- getInfo(format: TextureFormat): TextureFormatInfo {
26
- return getTextureFormatInfo(format);
27
- }
28
-
29
44
  /** Checks if a texture format is color */
30
45
  isColor(format: TextureFormat): format is TextureFormatColor {
31
- return format.startsWith('rgba') || format.startsWith('bgra') || format.startsWith('rgb');
46
+ return COLOR_FORMAT_PREFIXES.some(prefix => format.startsWith(prefix));
32
47
  }
33
48
 
34
49
  /** Checks if a texture format is depth or stencil */
35
- isDepthStencil(format: TextureFormat): boolean {
36
- return format.startsWith('depth') || format.startsWith('stencil');
50
+ isDepthStencil(format: TextureFormat): format is TextureFormatDepthStencil {
51
+ return DEPTH_FORMAT_PREFIXES.some(prefix => format.startsWith(prefix));
37
52
  }
38
53
 
39
54
  /** Checks if a texture format is compressed */
40
55
  isCompressed(format: TextureFormat): format is TextureFormatCompressed {
41
- return COMPRESSED_TEXTURE_FORMAT_PREFIXES.some(prefix => (format as string).startsWith(prefix));
56
+ return COMPRESSED_TEXTURE_FORMAT_PREFIXES.some(prefix => format.startsWith(prefix));
42
57
  }
43
58
 
44
- /**
45
- * Returns the "static" capabilities of a texture format.
46
- * @note Needs to be checked against current device
47
- */
48
- getCapabilities(format: TextureFormat): TextureFormatCapabilities {
49
- const info = getTextureFormatDefinition(format);
50
-
51
- const formatCapabilities: Required<TextureFormatCapabilities> = {
52
- format,
53
- create: info.f ?? true,
54
- render: info.render ?? true,
55
- filter: info.filter ?? true,
56
- blend: info.blend ?? true,
57
- store: info.store ?? true
58
- };
59
-
60
- const formatInfo = getTextureFormatInfo(format);
61
- const isDepthStencil = format.startsWith('depth') || format.startsWith('stencil');
62
- const isSigned = formatInfo?.signed;
63
- const isInteger = formatInfo?.integer;
64
- const isWebGLSpecific = formatInfo?.webgl;
59
+ /** Returns information about a texture format, e.g. attachment type, components, byte length and flags (integer, signed, normalized) */
60
+ getInfo(format: TextureFormat): TextureFormatInfo {
61
+ return getTextureFormatInfo(format);
62
+ }
65
63
 
66
- // signed formats are not renderable
67
- formatCapabilities.render &&= !isSigned;
68
- // signed and integer formats are not filterable
69
- formatCapabilities.filter &&= !isDepthStencil && !isSigned && !isInteger && !isWebGLSpecific;
64
+ /** "static" capabilities of a texture format. @note Needs to be adjusted against current device */
65
+ getCapabilities(format: TextureFormat): TextureFormatCapabilities {
66
+ return getTextureFormatCapabilities(format);
67
+ }
70
68
 
71
- return formatCapabilities;
69
+ /** Computes the memory layout for a texture, in particular including row byte alignment */
70
+ computeMemoryLayout(opts: TextureMemoryLayoutOptions): TextureMemoryLayout {
71
+ return computeTextureMemoryLayout(opts);
72
72
  }
73
73
  }
74
74
 
75
75
  export const textureFormatDecoder = new TextureFormatDecoder();
76
76
 
77
- // HELPERS
77
+ // HELPERS - MEMORY LAYOUT
78
+
79
+ /** Get the memory layout of a texture */
80
+ function computeTextureMemoryLayout({
81
+ format,
82
+ width,
83
+ height,
84
+ depth,
85
+ byteAlignment
86
+ }: TextureMemoryLayoutOptions): TextureMemoryLayout {
87
+ const {bytesPerPixel} = textureFormatDecoder.getInfo(format);
88
+ // WebGPU requires bytesPerRow to be a multiple of 256.
89
+ const unpaddedBytesPerRow = width * bytesPerPixel;
90
+ const bytesPerRow = Math.ceil(unpaddedBytesPerRow / byteAlignment) * byteAlignment;
91
+ const rowsPerImage = height;
92
+ const byteLength = bytesPerRow * rowsPerImage * depth;
93
+
94
+ return {
95
+ bytesPerPixel,
96
+ bytesPerRow,
97
+ rowsPerImage,
98
+ depthOrArrayLayers: depth,
99
+ bytesPerImage: bytesPerRow * rowsPerImage,
100
+ byteLength
101
+ };
102
+ }
103
+
104
+ // HELPERS - CAPABILITIES
105
+
106
+ function getTextureFormatCapabilities(format: TextureFormat): TextureFormatCapabilities {
107
+ const info = getTextureFormatDefinition(format);
108
+
109
+ const formatCapabilities: Required<TextureFormatCapabilities> = {
110
+ format,
111
+ create: info.f ?? true,
112
+ render: info.render ?? true,
113
+ filter: info.filter ?? true,
114
+ blend: info.blend ?? true,
115
+ store: info.store ?? true
116
+ };
117
+
118
+ const formatInfo = getTextureFormatInfo(format);
119
+ const isDepthStencil = format.startsWith('depth') || format.startsWith('stencil');
120
+ const isSigned = formatInfo?.signed;
121
+ const isInteger = formatInfo?.integer;
122
+ const isWebGLSpecific = formatInfo?.webgl;
123
+
124
+ // signed formats are not renderable
125
+ formatCapabilities.render &&= !isSigned;
126
+ // signed and integer formats are not filterable
127
+ formatCapabilities.filter &&= !isDepthStencil && !isSigned && !isInteger && !isWebGLSpecific;
128
+
129
+ return formatCapabilities;
130
+ }
131
+
132
+ // HELPER - FORMAT INFO
78
133
 
79
134
  /**
80
135
  * Decodes a texture format, returning e.g. attatchment type, components, byte length and flags (integer, signed, normalized)
81
136
  */
82
- function getTextureFormatInfo(format: TextureFormat): TextureFormatInfo {
137
+ export function getTextureFormatInfo(format: TextureFormat): TextureFormatInfo {
83
138
  let formatInfo: TextureFormatInfo = getTextureFormatInfoUsingTable(format);
84
139
 
85
140
  if (textureFormatDecoder.isCompressed(format)) {
@@ -2,7 +2,7 @@
2
2
  // SPDX-License-Identifier: MIT
3
3
  // Copyright (c) vis.gl contributors
4
4
 
5
- import {NormalizedDataType} from '../data-types/data-types';
5
+ import {NormalizedDataType, DataTypeArray, NormalizedDataTypeArray} from '../data-types/data-types';
6
6
 
7
7
  /** Information about the structure of a texture format */
8
8
  export type TextureFormatInfo = {
@@ -58,6 +58,33 @@ export type TextureFormatCapabilities = {
58
58
  store: TextureFeature | boolean;
59
59
  };
60
60
 
61
+ /**
62
+ * Memory layout for reading/writing data to a texture's memory.
63
+ *
64
+ * @note Due to alignment, GPU texture data is typically not contiguous.
65
+ *
66
+ * @note GPU texure data must be accessed according to this layout.
67
+ * - On CPU, only the range of rows that are actually read or written need to be allocated.
68
+ * - However, space for the full, padded/aligned rows must be allocated in the buffer,
69
+ * even if just a partial horizontal range `{x, width}` is actually read or written.
70
+ *
71
+ * @note byteLength = bytesPerRow * rowsPerImage * depthOrArrayLayers.
72
+ */
73
+ export type TextureMemoryLayout = {
74
+ /** Total length in bytes */
75
+ byteLength: number;
76
+ /** Number of images */
77
+ depthOrArrayLayers: number;
78
+ /** Stride between successive images (Use when depthOrArrayLayers > 1) */
79
+ bytesPerImage: number;
80
+ /** Number of rows per image */
81
+ rowsPerImage: number;
82
+ /** Number of bytes per row (padded) */
83
+ bytesPerRow: number;
84
+ /** Number of bytes per pixel */
85
+ bytesPerPixel: number;
86
+ };
87
+
61
88
  /**
62
89
  * These represent the main compressed texture formats
63
90
  * Each format typically has a number of more specific subformats
@@ -133,7 +160,7 @@ export type TextureFormatColorUncompressed =
133
160
  | TextureFormatPacked16
134
161
  | TextureFormatPacked32;
135
162
 
136
- type TextureFormatUnorm8 =
163
+ export type TextureFormatUnorm8 =
137
164
  | 'r8unorm'
138
165
  | 'rg8unorm'
139
166
  | 'rgb8unorm-webgl'
@@ -142,32 +169,36 @@ type TextureFormatUnorm8 =
142
169
  | 'bgra8unorm'
143
170
  | 'bgra8unorm-srgb';
144
171
 
145
- type TextureFormatSnorm8 = 'r8snorm' | 'rg8snorm' | 'rgb8snorm-webgl' | 'rgba8snorm';
172
+ export type TextureFormatSnorm8 = 'r8snorm' | 'rg8snorm' | 'rgb8snorm-webgl' | 'rgba8snorm';
146
173
 
147
- type TextureFormatUint8 = 'r8uint' | 'rg8uint' | 'rgba8uint';
174
+ export type TextureFormatUint8 = 'r8uint' | 'rg8uint' | 'rgba8uint';
148
175
 
149
- type TextureFormatSint8 = 'r8sint' | 'rg8sint' | 'rgba8sint';
176
+ export type TextureFormatSint8 = 'r8sint' | 'rg8sint' | 'rgba8sint';
150
177
 
151
- type TextureFormatUnorm16 = 'r16unorm' | 'rg16unorm' | 'rgb16unorm-webgl' | 'rgba16unorm';
178
+ export type TextureFormatUnorm16 = 'r16unorm' | 'rg16unorm' | 'rgb16unorm-webgl' | 'rgba16unorm';
152
179
 
153
- type TextureFormatSnorm16 = 'r16snorm' | 'rg16snorm' | 'rgb16snorm-webgl' | 'rgba16snorm';
180
+ export type TextureFormatSnorm16 = 'r16snorm' | 'rg16snorm' | 'rgb16snorm-webgl' | 'rgba16snorm';
154
181
 
155
- type TextureFormatUint16 = 'r16uint' | 'rg16uint' | 'rgba16uint';
182
+ export type TextureFormatUint16 = 'r16uint' | 'rg16uint' | 'rgba16uint';
156
183
 
157
- type TextureFormatSint16 = 'r16sint' | 'rg16sint' | 'rgba16sint';
184
+ export type TextureFormatSint16 = 'r16sint' | 'rg16sint' | 'rgba16sint';
158
185
 
159
- type TextureFormatFloat16 = 'r16float' | 'rg16float' | 'rgba16float';
186
+ export type TextureFormatFloat16 = 'r16float' | 'rg16float' | 'rgba16float';
160
187
 
161
188
  // 96-bit formats (deprecated!)
162
- type TextureFormatUint32 = 'r32uint' | 'rg32uint' | 'rgba32uint';
189
+ export type TextureFormatUint32 = 'r32uint' | 'rg32uint' | 'rgba32uint';
163
190
 
164
- type TextureFormatSint32 = 'r32sint' | 'rg32sint' | 'rgba32sint';
191
+ export type TextureFormatSint32 = 'r32sint' | 'rg32sint' | 'rgba32sint';
165
192
 
166
- type TextureFormatFloat32 = 'r32float' | 'rg32float' | 'rgb32float-webgl' | 'rgba32float';
193
+ export type TextureFormatFloat32 = 'r32float' | 'rg32float' | 'rgb32float-webgl' | 'rgba32float';
167
194
 
168
- type TextureFormatPacked16 = 'rgba4unorm-webgl' | 'rgb565unorm-webgl' | 'rgb5a1unorm-webgl';
195
+ export type TextureFormatPacked16 = 'rgba4unorm-webgl' | 'rgb565unorm-webgl' | 'rgb5a1unorm-webgl';
169
196
 
170
- type TextureFormatPacked32 = 'rgb9e5ufloat' | 'rg11b10ufloat' | 'rgb10a2unorm' | 'rgb10a2uint';
197
+ export type TextureFormatPacked32 =
198
+ | 'rgb9e5ufloat'
199
+ | 'rg11b10ufloat'
200
+ | 'rgb10a2unorm'
201
+ | 'rgb10a2uint';
171
202
 
172
203
  export type TextureFormatCompressed =
173
204
  | 'bc1-rgb-unorm-webgl'
@@ -245,6 +276,14 @@ export type TextureFormatCompressed =
245
276
 
246
277
  // Texture format helper types
247
278
 
279
+ export type TextureFormatTypedArray<T extends TextureFormat> = DataTypeArray<
280
+ TextureFormatDataType<T>
281
+ >;
282
+
283
+ export type TextureFormatNormalizedTypedArray<T extends TextureFormat> = NormalizedDataTypeArray<
284
+ TextureFormatDataType<T>
285
+ >;
286
+
248
287
  export type TextureFormatDataType<T extends TextureFormat> = T extends TextureFormatUint8
249
288
  ? 'uint8'
250
289
  : T extends TextureFormatSint8
@@ -0,0 +1,60 @@
1
+ // luma.gl
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) vis.gl contributors
4
+
5
+ import {TypedArray} from '@math.gl/types';
6
+ import {type TextureFormat, type TextureMemoryLayout} from './texture-formats';
7
+ import {textureFormatDecoder} from './texture-format-decoder';
8
+
9
+ export function getTextureImageView<T extends TextureFormat>(
10
+ arrayBuffer: ArrayBuffer,
11
+ memoryLayout: TextureMemoryLayout,
12
+ format: T,
13
+ image = 0
14
+ ) {
15
+ const formatInfo = textureFormatDecoder.getInfo(format);
16
+ const bytesPerComponent = formatInfo.bytesPerPixel / formatInfo.components;
17
+ const {bytesPerImage} = memoryLayout;
18
+ const offset = bytesPerImage * image;
19
+ const totalPixels = memoryLayout.bytesPerImage / bytesPerComponent;
20
+
21
+ switch (format) {
22
+ case 'rgba8unorm':
23
+ case 'bgra8unorm':
24
+ case 'rgba8uint':
25
+ return new Uint8Array(arrayBuffer, offset, totalPixels);
26
+ case 'r8unorm':
27
+ return new Uint8Array(arrayBuffer, offset, totalPixels);
28
+ case 'r16uint':
29
+ case 'rgba16uint':
30
+ return new Uint16Array(arrayBuffer, offset, totalPixels);
31
+ case 'r32uint':
32
+ case 'rgba32uint':
33
+ return new Uint32Array(arrayBuffer, offset, totalPixels);
34
+ case 'r32float':
35
+ return new Float32Array(arrayBuffer, offset, totalPixels);
36
+ case 'rgba16float':
37
+ return new Uint16Array(arrayBuffer, offset, totalPixels); // 4 channels
38
+ case 'rgba32float':
39
+ return new Float32Array(arrayBuffer, offset, totalPixels);
40
+ default:
41
+ throw new Error(`Unsupported format: ${format}`);
42
+ }
43
+ }
44
+
45
+ export function setTextureImageData<T extends TextureFormat>(
46
+ arrayBuffer: ArrayBuffer,
47
+ memoryLayout: TextureMemoryLayout,
48
+ format: T,
49
+ data: TypedArray,
50
+ image = 0
51
+ ): void {
52
+ const offset = 0; // memoryLayout.bytesPerImage * image;
53
+
54
+ const totalPixels = memoryLayout.bytesPerImage / memoryLayout.bytesPerPixel;
55
+ const subArray = data.subarray(0, totalPixels);
56
+
57
+ const typedArray = getTextureImageView(arrayBuffer, memoryLayout, format, image);
58
+
59
+ typedArray.set(subArray, offset);
60
+ }