@luma.gl/effects 9.2.0-alpha.1 → 9.2.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.
package/dist/dist.dev.js CHANGED
@@ -65,6 +65,7 @@ var __exports__ = (() => {
65
65
  DeviceLimits: () => DeviceLimits,
66
66
  ExternalTexture: () => ExternalTexture,
67
67
  Framebuffer: () => Framebuffer,
68
+ PipelineLayout: () => PipelineLayout,
68
69
  QuerySet: () => QuerySet,
69
70
  RenderPass: () => RenderPass,
70
71
  RenderPipeline: () => RenderPipeline,
@@ -72,30 +73,31 @@ var __exports__ = (() => {
72
73
  Sampler: () => Sampler,
73
74
  Shader: () => Shader,
74
75
  Texture: () => Texture,
76
+ TextureFormatDecoder: () => TextureFormatDecoder,
75
77
  TextureView: () => TextureView,
76
78
  TransformFeedback: () => TransformFeedback,
77
79
  UniformBlock: () => UniformBlock,
78
80
  UniformBufferLayout: () => UniformBufferLayout,
79
81
  UniformStore: () => UniformStore,
80
82
  VertexArray: () => VertexArray,
81
- _BufferLayoutHelper: () => BufferLayoutHelper,
82
83
  _getTextureFormatDefinition: () => getTextureFormatDefinition,
83
84
  _getTextureFormatTable: () => getTextureFormatTable,
84
85
  getAttributeInfosFromLayouts: () => getAttributeInfosFromLayouts,
85
86
  getAttributeShaderTypeInfo: () => getAttributeShaderTypeInfo,
86
- getDataTypeFromTypedArray: () => getDataTypeFromTypedArray,
87
+ getDataType: () => getDataType,
87
88
  getDataTypeInfo: () => getDataTypeInfo,
89
+ getNormalizedDataType: () => getNormalizedDataType,
88
90
  getScratchArray: () => getScratchArray,
89
- getTextureFormatCapabilities: () => getTextureFormatCapabilities,
90
- getTextureFormatInfo: () => getTextureFormatInfo,
91
- getTypedArrayFromDataType: () => getTypedArrayFromDataType,
91
+ getTypedArrayConstructor: () => getTypedArrayConstructor,
92
92
  getVariableShaderTypeInfo: () => getVariableShaderTypeInfo,
93
93
  getVertexFormatFromAttribute: () => getVertexFormatFromAttribute,
94
94
  getVertexFormatInfo: () => getVertexFormatInfo,
95
95
  log: () => log,
96
96
  luma: () => luma,
97
- makeNormalizedDataType: () => makeNormalizedDataType,
98
- makeVertexFormat: () => makeVertexFormat
97
+ makeVertexFormat: () => makeVertexFormat,
98
+ readPixel: () => readPixel,
99
+ textureFormatDecoder: () => textureFormatDecoder,
100
+ writePixel: () => writePixel
99
101
  });
100
102
 
101
103
  // ../../node_modules/@probe.gl/stats/dist/utils/hi-res-timestamp.js
@@ -336,7 +338,7 @@ var __exports__ = (() => {
336
338
  }
337
339
 
338
340
  // ../../node_modules/@probe.gl/env/dist/index.js
339
- var VERSION = true ? "4.0.7" : "untranspiled source";
341
+ var VERSION = true ? "4.1.0" : "untranspiled source";
340
342
 
341
343
  // ../../node_modules/@probe.gl/log/dist/utils/local-storage.js
342
344
  function getStorage(type) {
@@ -911,10 +913,6 @@ var __exports__ = (() => {
911
913
  clone(props) {
912
914
  return this.device.createBuffer({ ...this.props, ...props });
913
915
  }
914
- /** Read data synchronously. @note WebGL2 only */
915
- readSyncWebGL(byteOffset, byteLength) {
916
- throw new Error("not implemented");
917
- }
918
916
  /** A partial CPU-side copy of the data in this buffer, for debugging purposes */
919
917
  debugData = new ArrayBuffer(0);
920
918
  /** This doesn't handle partial non-zero offset updates correctly */
@@ -960,10 +958,10 @@ var __exports__ = (() => {
960
958
  byteOffset: 0,
961
959
  data: null,
962
960
  indexType: "uint16",
963
- mappedAtCreation: false
961
+ onMapped: void 0
964
962
  });
965
963
 
966
- // ../core/src/shadertypes/utils/decode-data-types.ts
964
+ // ../core/src/shadertypes/data-types/decode-data-types.ts
967
965
  function getDataTypeInfo(type) {
968
966
  const [signedType, primitiveType, byteLength] = NORMALIZED_TYPE_MAP[type];
969
967
  const normalized = type.includes("norm");
@@ -978,7 +976,7 @@ var __exports__ = (() => {
978
976
  signed
979
977
  };
980
978
  }
981
- function makeNormalizedDataType(signedDataType) {
979
+ function getNormalizedDataType(signedDataType) {
982
980
  const dataType = signedDataType;
983
981
  switch (dataType) {
984
982
  case "uint8":
@@ -1003,72 +1001,117 @@ var __exports__ = (() => {
1003
1001
  return size + (4 - size % 4) % 4;
1004
1002
  }
1005
1003
  }
1006
- function getDataTypeFromTypedArray(arrayOrType) {
1007
- const type = ArrayBuffer.isView(arrayOrType) ? arrayOrType.constructor : arrayOrType;
1008
- switch (type) {
1009
- case Float32Array:
1010
- return "float32";
1011
- case Uint16Array:
1012
- return "uint16";
1013
- case Uint32Array:
1014
- return "uint32";
1015
- case Uint8Array:
1016
- case Uint8ClampedArray:
1017
- return "uint8";
1018
- case Int8Array:
1019
- return "sint8";
1020
- case Int16Array:
1021
- return "sint16";
1022
- case Int32Array:
1023
- return "sint32";
1024
- default:
1025
- throw new Error(type.constructor.name);
1004
+ function getDataType(arrayOrType) {
1005
+ const Constructor = ArrayBuffer.isView(arrayOrType) ? arrayOrType.constructor : arrayOrType;
1006
+ if (Constructor === Uint8ClampedArray) {
1007
+ return "uint8";
1008
+ }
1009
+ const info = Object.values(NORMALIZED_TYPE_MAP).find((entry) => Constructor === entry[4]);
1010
+ if (!info) {
1011
+ throw new Error(Constructor.name);
1026
1012
  }
1013
+ return info[0];
1027
1014
  }
1028
- function getTypedArrayFromDataType(type) {
1029
- switch (type) {
1030
- case "f32":
1031
- case "float32":
1032
- return Float32Array;
1033
- case "u32":
1034
- case "uint32":
1035
- return Uint32Array;
1036
- case "i32":
1037
- case "sint32":
1038
- return Int32Array;
1015
+ function getTypedArrayConstructor(type) {
1016
+ const [, , , , Constructor] = NORMALIZED_TYPE_MAP[type];
1017
+ return Constructor;
1018
+ }
1019
+ var NORMALIZED_TYPE_MAP = {
1020
+ uint8: ["uint8", "u32", 1, false, Uint8Array],
1021
+ sint8: ["sint8", "i32", 1, false, Int8Array],
1022
+ unorm8: ["uint8", "f32", 1, true, Uint8Array],
1023
+ snorm8: ["sint8", "f32", 1, true, Int8Array],
1024
+ uint16: ["uint16", "u32", 2, false, Uint16Array],
1025
+ sint16: ["sint16", "i32", 2, false, Int16Array],
1026
+ unorm16: ["uint16", "u32", 2, true, Uint16Array],
1027
+ snorm16: ["sint16", "i32", 2, true, Int16Array],
1028
+ float16: ["float16", "f16", 2, false, Uint16Array],
1029
+ float32: ["float32", "f32", 4, false, Float32Array],
1030
+ uint32: ["uint32", "u32", 4, false, Uint32Array],
1031
+ sint32: ["sint32", "i32", 4, false, Int32Array]
1032
+ };
1033
+
1034
+ // ../core/src/shadertypes/vertex-arrays/decode-vertex-format.ts
1035
+ function getVertexFormatInfo(format) {
1036
+ let webglOnly;
1037
+ if (format.endsWith("-webgl")) {
1038
+ format.replace("-webgl", "");
1039
+ webglOnly = true;
1040
+ }
1041
+ const [type_, count] = format.split("x");
1042
+ const type = type_;
1043
+ const components = count ? parseInt(count) : 1;
1044
+ const decodedType = getDataTypeInfo(type);
1045
+ const result = {
1046
+ type,
1047
+ components,
1048
+ byteLength: decodedType.byteLength * components,
1049
+ integer: decodedType.integer,
1050
+ signed: decodedType.signed,
1051
+ normalized: decodedType.normalized
1052
+ };
1053
+ if (webglOnly) {
1054
+ result.webglOnly = true;
1055
+ }
1056
+ return result;
1057
+ }
1058
+ function makeVertexFormat(signedDataType, components, normalized) {
1059
+ const dataType = normalized ? getNormalizedDataType(signedDataType) : signedDataType;
1060
+ switch (dataType) {
1061
+ case "unorm8":
1062
+ if (components === 1) {
1063
+ return "unorm8";
1064
+ }
1065
+ if (components === 3) {
1066
+ return "unorm8x3-webgl";
1067
+ }
1068
+ return `${dataType}x${components}`;
1069
+ case "snorm8":
1070
+ case "uint8":
1071
+ case "sint8":
1039
1072
  case "uint16":
1040
- case "unorm16":
1041
- return Uint16Array;
1042
1073
  case "sint16":
1074
+ case "unorm16":
1043
1075
  case "snorm16":
1044
- return Int16Array;
1045
- case "uint8":
1046
- case "unorm8":
1047
- return Uint8Array;
1048
- case "sint8":
1049
- case "snorm8":
1050
- return Int8Array;
1051
- case "f16":
1076
+ case "float16":
1077
+ if (components === 1 || components === 3) {
1078
+ throw new Error(`size: ${components}`);
1079
+ }
1080
+ return `${dataType}x${components}`;
1052
1081
  default:
1053
- throw new Error(type);
1082
+ return components === 1 ? dataType : `${dataType}x${components}`;
1054
1083
  }
1055
1084
  }
1056
- var NORMALIZED_TYPE_MAP = {
1057
- uint8: ["uint8", "u32", 1, false],
1058
- sint8: ["sint8", "i32", 1, false],
1059
- unorm8: ["uint8", "f32", 1, true],
1060
- snorm8: ["sint8", "f32", 1, true],
1061
- uint16: ["uint16", "u32", 2, false],
1062
- sint16: ["sint16", "i32", 2, false],
1063
- unorm16: ["uint16", "u32", 2, true],
1064
- snorm16: ["sint16", "i32", 2, true],
1065
- float16: ["float16", "f16", 2, false],
1066
- float32: ["float32", "f32", 4, false],
1067
- uint32: ["uint32", "u32", 4, false],
1068
- sint32: ["sint32", "i32", 4, false]
1069
- };
1085
+ function getVertexFormatFromAttribute(typedArray, size, normalized) {
1086
+ if (!size || size > 4) {
1087
+ throw new Error(`size ${size}`);
1088
+ }
1089
+ const components = size;
1090
+ const signedDataType = getDataType(typedArray);
1091
+ return makeVertexFormat(signedDataType, components, normalized);
1092
+ }
1093
+ function getCompatibleVertexFormat(opts) {
1094
+ let vertexType;
1095
+ switch (opts.primitiveType) {
1096
+ case "f32":
1097
+ vertexType = "float32";
1098
+ break;
1099
+ case "i32":
1100
+ vertexType = "sint32";
1101
+ break;
1102
+ case "u32":
1103
+ vertexType = "uint32";
1104
+ break;
1105
+ case "f16":
1106
+ return opts.components <= 2 ? "float16x2" : "float16x4";
1107
+ }
1108
+ if (opts.components === 1) {
1109
+ return vertexType;
1110
+ }
1111
+ return `${vertexType}x${opts.components}`;
1112
+ }
1070
1113
 
1071
- // ../core/src/shadertypes/utils/texture-format-table.ts
1114
+ // ../core/src/shadertypes/textures/texture-format-table.ts
1072
1115
  var texture_compression_bc = "texture-compression-bc";
1073
1116
  var texture_compression_astc = "texture-compression-astc";
1074
1117
  var texture_compression_etc2 = "texture-compression-etc2";
@@ -1093,73 +1136,65 @@ var __exports__ = (() => {
1093
1136
  function getTextureFormatTable() {
1094
1137
  return TEXTURE_FORMAT_TABLE;
1095
1138
  }
1096
- var TEXTURE_FORMAT_TABLE = {
1139
+ var TEXTURE_FORMAT_COLOR_DEPTH_TABLE = {
1097
1140
  // 8-bit formats
1098
1141
  "r8unorm": {},
1099
- "r8snorm": { render: snorm8_renderable },
1100
- "r8uint": {},
1101
- "r8sint": {},
1102
- // 16-bit formats
1103
1142
  "rg8unorm": {},
1104
- "rg8snorm": { render: snorm8_renderable },
1105
- "rg8uint": {},
1106
- "rg8sint": {},
1107
- "r16uint": {},
1108
- "r16sint": {},
1109
- "r16float": { render: float16_renderable, filter: "float16-filterable-webgl" },
1110
- "r16unorm-webgl": { f: norm16_renderable },
1111
- "r16snorm-webgl": { f: snorm16_renderable },
1112
- // Packed 16-bit formats
1113
- "rgba4unorm-webgl": { channels: "rgba", bitsPerChannel: [4, 4, 4, 4], packed: true },
1114
- "rgb565unorm-webgl": { channels: "rgb", bitsPerChannel: [5, 6, 5, 0], packed: true },
1115
- "rgb5a1unorm-webgl": { channels: "rgba", bitsPerChannel: [5, 5, 5, 1], packed: true },
1116
- // 24-bit formats
1117
1143
  "rgb8unorm-webgl": {},
1118
- "rgb8snorm-webgl": {},
1119
- // 32-bit formats
1120
1144
  "rgba8unorm": {},
1121
1145
  "rgba8unorm-srgb": {},
1146
+ "r8snorm": { render: snorm8_renderable },
1147
+ "rg8snorm": { render: snorm8_renderable },
1148
+ "rgb8snorm-webgl": {},
1122
1149
  "rgba8snorm": { render: snorm8_renderable },
1150
+ "r8uint": {},
1151
+ "rg8uint": {},
1123
1152
  "rgba8uint": {},
1153
+ "r8sint": {},
1154
+ "rg8sint": {},
1124
1155
  "rgba8sint": {},
1125
- // 32-bit, reverse colors, webgpu only
1126
1156
  "bgra8unorm": {},
1127
1157
  "bgra8unorm-srgb": {},
1158
+ "r16unorm": { f: norm16_renderable },
1159
+ "rg16unorm": { render: norm16_renderable },
1160
+ "rgb16unorm-webgl": { f: norm16_renderable },
1161
+ // rgb not renderable
1162
+ "rgba16unorm": { render: norm16_renderable },
1163
+ "r16snorm": { f: snorm16_renderable },
1164
+ "rg16snorm": { render: snorm16_renderable },
1165
+ "rgb16snorm-webgl": { f: norm16_renderable },
1166
+ // rgb not renderable
1167
+ "rgba16snorm": { render: snorm16_renderable },
1168
+ "r16uint": {},
1128
1169
  "rg16uint": {},
1170
+ "rgba16uint": {},
1171
+ "r16sint": {},
1129
1172
  "rg16sint": {},
1173
+ "rgba16sint": {},
1174
+ "r16float": { render: float16_renderable, filter: "float16-filterable-webgl" },
1130
1175
  "rg16float": { render: float16_renderable, filter: float16_filterable },
1131
- "rg16unorm-webgl": { render: norm16_renderable },
1132
- "rg16snorm-webgl": { render: snorm16_renderable },
1176
+ "rgba16float": { render: float16_renderable, filter: float16_filterable },
1133
1177
  "r32uint": {},
1178
+ "rg32uint": {},
1179
+ "rgba32uint": {},
1134
1180
  "r32sint": {},
1181
+ "rg32sint": {},
1182
+ "rgba32sint": {},
1135
1183
  "r32float": { render: float32_renderable, filter: float32_filterable },
1184
+ "rg32float": { render: false, filter: float32_filterable },
1185
+ "rgb32float-webgl": { render: float32_renderable, filter: float32_filterable },
1186
+ "rgba32float": { render: float32_renderable, filter: float32_filterable },
1187
+ // Packed 16-bit formats
1188
+ "rgba4unorm-webgl": { channels: "rgba", bitsPerChannel: [4, 4, 4, 4], packed: true },
1189
+ "rgb565unorm-webgl": { channels: "rgb", bitsPerChannel: [5, 6, 5, 0], packed: true },
1190
+ "rgb5a1unorm-webgl": { channels: "rgba", bitsPerChannel: [5, 5, 5, 1], packed: true },
1136
1191
  // Packed 32 bit formats
1137
1192
  "rgb9e5ufloat": { channels: "rgb", packed: true, render: rgb9e5ufloat_renderable },
1138
1193
  // , filter: true},
1139
1194
  "rg11b10ufloat": { channels: "rgb", bitsPerChannel: [11, 11, 10, 0], packed: true, p: 1, render: float32_renderable },
1140
1195
  "rgb10a2unorm": { channels: "rgba", bitsPerChannel: [10, 10, 10, 2], packed: true, p: 1 },
1141
1196
  "rgb10a2uint": { channels: "rgba", bitsPerChannel: [10, 10, 10, 2], packed: true, p: 1 },
1142
- // 48-bit formats
1143
- "rgb16unorm-webgl": { f: norm16_renderable },
1144
- // rgb not renderable
1145
- "rgb16snorm-webgl": { f: norm16_renderable },
1146
- // rgb not renderable
1147
- // 64-bit formats
1148
- "rg32uint": {},
1149
- "rg32sint": {},
1150
- "rg32float": { render: false, filter: float32_filterable },
1151
- "rgba16uint": {},
1152
- "rgba16sint": {},
1153
- "rgba16float": { render: float16_renderable, filter: float16_filterable },
1154
- "rgba16unorm-webgl": { render: norm16_renderable },
1155
- "rgba16snorm-webgl": { render: snorm16_renderable },
1156
- // 96-bit formats (deprecated!)
1157
- "rgb32float-webgl": { render: float32_renderable, filter: float32_filterable },
1158
- // 128-bit formats
1159
- "rgba32uint": {},
1160
- "rgba32sint": {},
1161
- "rgba32float": { render: float32_renderable, filter: float32_filterable },
1162
- // Depth/stencil
1197
+ // Depth/stencil Formats
1163
1198
  // Depth and stencil formats
1164
1199
  stencil8: { attachment: "stencil", bitsPerChannel: [8, 0, 0, 0], dataType: "uint8" },
1165
1200
  "depth16unorm": { attachment: "depth", bitsPerChannel: [16, 0, 0, 0], dataType: "uint16" },
@@ -1168,7 +1203,9 @@ var __exports__ = (() => {
1168
1203
  // The depth component of the "depth24plus" and "depth24plus-stencil8" formats may be implemented as either a 24-bit depth value or a "depth32float" value.
1169
1204
  "depth24plus-stencil8": { attachment: "depth-stencil", bitsPerChannel: [24, 8, 0, 0], packed: true },
1170
1205
  // "depth32float-stencil8" feature
1171
- "depth32float-stencil8": { attachment: "depth-stencil", bitsPerChannel: [32, 8, 0, 0], packed: true },
1206
+ "depth32float-stencil8": { attachment: "depth-stencil", bitsPerChannel: [32, 8, 0, 0], packed: true }
1207
+ };
1208
+ var TEXTURE_FORMAT_COMPRESSED_TABLE = {
1172
1209
  // BC compressed formats: check device.features.has("texture-compression-bc");
1173
1210
  "bc1-rgb-unorm-webgl": { f: texture_compression_bc },
1174
1211
  "bc1-rgb-unorm-srgb-webgl": { f: texture_compression_bc },
@@ -1239,8 +1276,12 @@ var __exports__ = (() => {
1239
1276
  "atc-rgba-unorm-webgl": { f: texture_compression_atc_webgl },
1240
1277
  "atc-rgbai-unorm-webgl": { f: texture_compression_atc_webgl }
1241
1278
  };
1279
+ var TEXTURE_FORMAT_TABLE = {
1280
+ ...TEXTURE_FORMAT_COLOR_DEPTH_TABLE,
1281
+ ...TEXTURE_FORMAT_COMPRESSED_TABLE
1282
+ };
1242
1283
 
1243
- // ../core/src/shadertypes/utils/decode-texture-format.ts
1284
+ // ../core/src/shadertypes/textures/texture-format-decoder.ts
1244
1285
  var COMPRESSED_TEXTURE_FORMAT_PREFIXES = [
1245
1286
  "bc1",
1246
1287
  "bc2",
@@ -1257,12 +1298,51 @@ var __exports__ = (() => {
1257
1298
  "pvrtc"
1258
1299
  ];
1259
1300
  var RGB_FORMAT_REGEX = /^(r|rg|rgb|rgba|bgra)([0-9]*)([a-z]*)(-srgb)?(-webgl)?$/;
1260
- function isTextureFormatCompressed(format) {
1261
- return COMPRESSED_TEXTURE_FORMAT_PREFIXES.some((prefix) => format.startsWith(prefix));
1262
- }
1301
+ var TextureFormatDecoder = class {
1302
+ /** Returns information about a texture format, e.g. attatchment type, components, byte length and flags (integer, signed, normalized) */
1303
+ getInfo(format) {
1304
+ return getTextureFormatInfo(format);
1305
+ }
1306
+ /** Checks if a texture format is color */
1307
+ isColor(format) {
1308
+ return format.startsWith("rgba") || format.startsWith("bgra") || format.startsWith("rgb");
1309
+ }
1310
+ /** Checks if a texture format is depth or stencil */
1311
+ isDepthStencil(format) {
1312
+ return format.startsWith("depth") || format.startsWith("stencil");
1313
+ }
1314
+ /** Checks if a texture format is compressed */
1315
+ isCompressed(format) {
1316
+ return COMPRESSED_TEXTURE_FORMAT_PREFIXES.some((prefix) => format.startsWith(prefix));
1317
+ }
1318
+ /**
1319
+ * Returns the "static" capabilities of a texture format.
1320
+ * @note Needs to be checked against current device
1321
+ */
1322
+ getCapabilities(format) {
1323
+ const info = getTextureFormatDefinition(format);
1324
+ const formatCapabilities = {
1325
+ format,
1326
+ create: info.f ?? true,
1327
+ render: info.render ?? true,
1328
+ filter: info.filter ?? true,
1329
+ blend: info.blend ?? true,
1330
+ store: info.store ?? true
1331
+ };
1332
+ const formatInfo = getTextureFormatInfo(format);
1333
+ const isDepthStencil = format.startsWith("depth") || format.startsWith("stencil");
1334
+ const isSigned = formatInfo?.signed;
1335
+ const isInteger = formatInfo?.integer;
1336
+ const isWebGLSpecific = formatInfo?.webgl;
1337
+ formatCapabilities.render &&= !isSigned;
1338
+ formatCapabilities.filter &&= !isDepthStencil && !isSigned && !isInteger && !isWebGLSpecific;
1339
+ return formatCapabilities;
1340
+ }
1341
+ };
1342
+ var textureFormatDecoder = new TextureFormatDecoder();
1263
1343
  function getTextureFormatInfo(format) {
1264
1344
  let formatInfo = getTextureFormatInfoUsingTable(format);
1265
- if (isTextureFormatCompressed(format)) {
1345
+ if (textureFormatDecoder.isCompressed(format)) {
1266
1346
  formatInfo.channels = "rgb";
1267
1347
  formatInfo.components = 3;
1268
1348
  formatInfo.bytesPerPixel = 1;
@@ -1316,25 +1396,6 @@ var __exports__ = (() => {
1316
1396
  }
1317
1397
  return formatInfo;
1318
1398
  }
1319
- function getTextureFormatCapabilities(format) {
1320
- const info = getTextureFormatDefinition(format);
1321
- const formatCapabilities = {
1322
- format,
1323
- create: info.f ?? true,
1324
- render: info.render ?? true,
1325
- filter: info.filter ?? true,
1326
- blend: info.blend ?? true,
1327
- store: info.store ?? true
1328
- };
1329
- const formatInfo = getTextureFormatInfo(format);
1330
- const isDepthStencil = format.startsWith("depth") || format.startsWith("stencil");
1331
- const isSigned = formatInfo?.signed;
1332
- const isInteger = formatInfo?.integer;
1333
- const isWebGLSpecific = formatInfo?.webgl;
1334
- formatCapabilities.render &&= !isSigned;
1335
- formatCapabilities.filter &&= !isDepthStencil && !isSigned && !isInteger && !isWebGLSpecific;
1336
- return formatCapabilities;
1337
- }
1338
1399
  function getTextureFormatInfoUsingTable(format) {
1339
1400
  const info = getTextureFormatDefinition(format);
1340
1401
  const bytesPerPixel = info.bytesPerPixel || 1;
@@ -1416,9 +1477,8 @@ var __exports__ = (() => {
1416
1477
  get [Symbol.toStringTag]() {
1417
1478
  return "Device";
1418
1479
  }
1419
- constructor(props) {
1420
- this.props = { ..._Device.defaultProps, ...props };
1421
- this.id = this.props.id || uid(this[Symbol.toStringTag].toLowerCase());
1480
+ toString() {
1481
+ return `Device(${this.id})`;
1422
1482
  }
1423
1483
  /** id of this device, primarily for debugging */
1424
1484
  id;
@@ -1430,12 +1490,24 @@ var __exports__ = (() => {
1430
1490
  statsManager = lumaStats;
1431
1491
  /** An abstract timestamp used for change tracking */
1432
1492
  timestamp = 0;
1493
+ /** True if this device has been reused during device creation (app has multiple references) */
1494
+ _reused = false;
1433
1495
  /** Used by other luma.gl modules to store data on the device */
1434
1496
  _lumaData = {};
1435
1497
  _textureCaps = {};
1498
+ constructor(props) {
1499
+ this.props = { ..._Device.defaultProps, ...props };
1500
+ this.id = this.props.id || uid(this[Symbol.toStringTag].toLowerCase());
1501
+ }
1502
+ getVertexFormatInfo(format) {
1503
+ return getVertexFormatInfo(format);
1504
+ }
1505
+ isVertexFormatSupported(format) {
1506
+ return true;
1507
+ }
1436
1508
  /** Returns information about a texture format, such as data type, channels, bits per channel, compression etc */
1437
1509
  getTextureFormatInfo(format) {
1438
- return getTextureFormatInfo(format);
1510
+ return textureFormatDecoder.getInfo(format);
1439
1511
  }
1440
1512
  /** Determines what operations are supported on a texture format on this particular device (checks against supported device features) */
1441
1513
  getTextureFormatCapabilities(format) {
@@ -1474,7 +1546,7 @@ var __exports__ = (() => {
1474
1546
  }
1475
1547
  /** Check if a specific texture format is GPU compressed */
1476
1548
  isTextureFormatCompressed(format) {
1477
- return isTextureFormatCompressed(format);
1549
+ return textureFormatDecoder.isCompressed(format);
1478
1550
  }
1479
1551
  // DEBUG METHODS
1480
1552
  pushDebugGroup(groupLabel) {
@@ -1498,12 +1570,40 @@ var __exports__ = (() => {
1498
1570
  incrementTimestamp() {
1499
1571
  return this.timestamp++;
1500
1572
  }
1501
- /** Report error (normally called for unhandled device errors) */
1502
- reportError(error, context) {
1573
+ /**
1574
+ * Reports Device errors in a way that optimizes for developer experience / debugging.
1575
+ * - Logs so that the console error links directly to the source code that generated the error.
1576
+ * - Includes the object that reported the error in the log message, even if the error is asynchronous.
1577
+ *
1578
+ * Conventions when calling reportError():
1579
+ * - Always call the returned function - to ensure error is logged, at the error site
1580
+ * - Follow with a call to device.debug() - to ensure that the debugger breaks at the error site
1581
+ *
1582
+ * @param error - the error to report. If needed, just create a new Error object with the appropriate message.
1583
+ * @param context - pass `this` as context, otherwise it may not be available in the debugger for async errors.
1584
+ * @returns the logger function returned by device.props.onError() so that it can be called from the error site.
1585
+ *
1586
+ * @example
1587
+ * device.reportError(new Error(...), this)();
1588
+ * device.debug();
1589
+ */
1590
+ reportError(error, context, ...args) {
1591
+ const isHandled = this.props.onError(error, context);
1592
+ if (!isHandled) {
1593
+ return log.error(error.message, context, ...args);
1594
+ }
1595
+ return () => {
1596
+ };
1597
+ }
1598
+ /** Break in the debugger - if device.props.debug is true */
1599
+ debug() {
1503
1600
  if (this.props.debug) {
1504
1601
  debugger;
1602
+ } else {
1603
+ const message = `'Type luma.log.set({debug: true}) in console to enable debug breakpoints',
1604
+ or create a device with the 'debug: true' prop.`;
1605
+ log.once(0, message)();
1505
1606
  }
1506
- this.props.onError(error, context);
1507
1607
  }
1508
1608
  /** Returns the default / primary canvas context. Throws an error if no canvas context is available (a WebGPU compute device) */
1509
1609
  getDefaultCanvasContext() {
@@ -1556,8 +1656,12 @@ var __exports__ = (() => {
1556
1656
  throw new Error("not implemented");
1557
1657
  }
1558
1658
  // IMPLEMENTATION
1659
+ /** Helper to get the canvas context props */
1660
+ static _getCanvasContextProps(props) {
1661
+ return props.createCanvasContext === true ? {} : props.createCanvasContext;
1662
+ }
1559
1663
  _getDeviceTextureFormatCapabilities(format) {
1560
- const genericCapabilities = getTextureFormatCapabilities(format);
1664
+ const genericCapabilities = textureFormatDecoder.getCapabilities(format);
1561
1665
  const checkFeature = (feature) => (typeof feature === "string" ? this.features.has(feature) : feature) ?? true;
1562
1666
  const supported = checkFeature(genericCapabilities.create);
1563
1667
  return {
@@ -1575,13 +1679,17 @@ var __exports__ = (() => {
1575
1679
  props = { data: props };
1576
1680
  }
1577
1681
  const newProps = { ...props };
1578
- if ((props.usage || 0) & Buffer2.INDEX && !props.indexType) {
1579
- if (props.data instanceof Uint32Array) {
1580
- newProps.indexType = "uint32";
1581
- } else if (props.data instanceof Uint16Array) {
1582
- newProps.indexType = "uint16";
1583
- } else {
1584
- log.warn("indices buffer content must be of type uint16 or uint32")();
1682
+ const usage = props.usage || 0;
1683
+ if (usage & Buffer2.INDEX) {
1684
+ if (!props.indexType) {
1685
+ if (props.data instanceof Uint32Array) {
1686
+ newProps.indexType = "uint32";
1687
+ } else if (props.data instanceof Uint16Array) {
1688
+ newProps.indexType = "uint16";
1689
+ }
1690
+ }
1691
+ if (!newProps.indexType) {
1692
+ throw new Error("indices buffer content must be of type uint16 or uint32");
1585
1693
  }
1586
1694
  }
1587
1695
  return newProps;
@@ -1596,11 +1704,16 @@ var __exports__ = (() => {
1596
1704
  // WebGL specific
1597
1705
  webgl: {},
1598
1706
  // Callbacks
1599
- onError: (error, context) => log.error(error.message, context)(),
1707
+ // eslint-disable-next-line handle-callback-err
1708
+ onError: (error, context) => {
1709
+ },
1600
1710
  onResize: (context, info) => {
1601
1711
  const [width, height] = context.getDevicePixelSize();
1602
- const [prevWidth, prevHeight] = info.oldPixelSize;
1603
- log.log(1, `${context} Resized ${prevWidth}x${prevHeight} => ${width}x${height}px`)();
1712
+ log.log(1, `${context} resized => ${width}x${height}px`)();
1713
+ },
1714
+ onPositionChange: (context, info) => {
1715
+ const [left, top] = context.getPosition();
1716
+ log.log(1, `${context} repositioned => ${left},${top}`)();
1604
1717
  },
1605
1718
  onVisibilityChange: (context) => log.log(1, `${context} Visibility changed ${context.isVisible}`)(),
1606
1719
  onDevicePixelRatioChange: (context, info) => log.log(1, `${context} DPR changed ${info.oldRatio} => ${context.devicePixelRatio}`)(),
@@ -1614,6 +1727,7 @@ var __exports__ = (() => {
1614
1727
  // Note: log setting is queried by the spector.js code
1615
1728
  debugSpectorJSUrl: void 0,
1616
1729
  // Experimental
1730
+ _reuseDevices: false,
1617
1731
  _requestMaxLimits: true,
1618
1732
  _cacheShaders: false,
1619
1733
  _cachePipelines: false,
@@ -1852,6 +1966,8 @@ var __exports__ = (() => {
1852
1966
  _initializedResolvers = withResolvers();
1853
1967
  _resizeObserver;
1854
1968
  _intersectionObserver;
1969
+ _position;
1970
+ destroyed = false;
1855
1971
  toString() {
1856
1972
  return `${this[Symbol.toStringTag]}(${this.id})`;
1857
1973
  }
@@ -1887,6 +2003,7 @@ var __exports__ = (() => {
1887
2003
  this.drawingBufferWidth = this.canvas.width;
1888
2004
  this.drawingBufferHeight = this.canvas.height;
1889
2005
  this.devicePixelRatio = globalThis.devicePixelRatio || 1;
2006
+ this._position = [0, 0];
1890
2007
  if (_CanvasContext.isHTMLCanvas(this.canvas)) {
1891
2008
  this._intersectionObserver = new IntersectionObserver(
1892
2009
  (entries) => this._handleIntersection(entries)
@@ -1899,8 +2016,14 @@ var __exports__ = (() => {
1899
2016
  this._resizeObserver.observe(this.canvas, { box: "content-box" });
1900
2017
  }
1901
2018
  setTimeout(() => this._observeDevicePixelRatio(), 0);
2019
+ if (this.props.trackPosition) {
2020
+ this._trackPosition();
2021
+ }
1902
2022
  }
1903
2023
  }
2024
+ destroy() {
2025
+ this.destroyed = true;
2026
+ }
1904
2027
  // SIZE METHODS
1905
2028
  /**
1906
2029
  * Returns the size covered by the canvas in CSS pixels
@@ -1910,6 +2033,9 @@ var __exports__ = (() => {
1910
2033
  getCSSSize() {
1911
2034
  return [this.cssWidth, this.cssHeight];
1912
2035
  }
2036
+ getPosition() {
2037
+ return this._position;
2038
+ }
1913
2039
  /**
1914
2040
  * Returns the size covered by the canvas in actual device pixels.
1915
2041
  * @note This can be different from the 'CSS' size of a canvas due to DPR scaling, and rounding to integer pixels
@@ -2025,12 +2151,14 @@ var __exports__ = (() => {
2025
2151
  }
2026
2152
  this._initializedResolvers.resolve();
2027
2153
  this.isInitialized = true;
2154
+ this.updatePosition();
2028
2155
  this.device.props.onResize(this, { oldPixelSize });
2029
2156
  }
2030
2157
  /** Monitor DPR changes */
2031
2158
  _observeDevicePixelRatio() {
2032
2159
  const oldRatio = this.devicePixelRatio;
2033
2160
  this.devicePixelRatio = window.devicePixelRatio;
2161
+ this.updatePosition();
2034
2162
  this.device.props.onDevicePixelRatioChange(this, { oldRatio });
2035
2163
  matchMedia(`(resolution: ${this.devicePixelRatio}dppx)`).addEventListener(
2036
2164
  "change",
@@ -2038,6 +2166,34 @@ var __exports__ = (() => {
2038
2166
  { once: true }
2039
2167
  );
2040
2168
  }
2169
+ /** Start tracking positions with a timer */
2170
+ _trackPosition(intervalMs = 100) {
2171
+ const intervalId = setInterval(() => {
2172
+ if (this.destroyed) {
2173
+ clearInterval(intervalId);
2174
+ } else {
2175
+ this.updatePosition();
2176
+ }
2177
+ }, intervalMs);
2178
+ }
2179
+ /**
2180
+ * Calculated the absolute position of the canvas
2181
+ * @note - getBoundingClientRect() is normally cheap but can be expensive
2182
+ * if called before browser has finished a reflow. Should not be the case here.
2183
+ */
2184
+ updatePosition() {
2185
+ const newRect = this.htmlCanvas?.getBoundingClientRect();
2186
+ if (newRect) {
2187
+ const position = [newRect.left, newRect.top];
2188
+ this._position ??= position;
2189
+ const positionChanged = position[0] !== this._position[0] || position[1] !== this._position[1];
2190
+ if (positionChanged) {
2191
+ const oldPosition = this._position;
2192
+ this._position = position;
2193
+ this.device.props.onPositionChange?.(this, { oldPosition });
2194
+ }
2195
+ }
2196
+ }
2041
2197
  };
2042
2198
  var CanvasContext = _CanvasContext;
2043
2199
  __publicField(CanvasContext, "defaultProps", {
@@ -2050,7 +2206,8 @@ var __exports__ = (() => {
2050
2206
  container: null,
2051
2207
  visible: true,
2052
2208
  alphaMode: "opaque",
2053
- colorSpace: "srgb"
2209
+ colorSpace: "srgb",
2210
+ trackPosition: false
2054
2211
  });
2055
2212
  function getContainer(container) {
2056
2213
  if (typeof container === "string") {
@@ -2838,7 +2995,7 @@ ${htmlLog}
2838
2995
  ...Resource.defaultProps
2839
2996
  });
2840
2997
 
2841
- // ../core/src/shadertypes/utils/decode-shader-types.ts
2998
+ // ../core/src/shadertypes/data-types/decode-shader-types.ts
2842
2999
  function getVariableShaderTypeInfo(format) {
2843
3000
  const decoded = UNIFORM_FORMATS[format];
2844
3001
  return decoded;
@@ -2991,86 +3148,6 @@ ${htmlLog}
2991
3148
  mat4x4h: "mat4x4<f16>"
2992
3149
  };
2993
3150
 
2994
- // ../core/src/shadertypes/utils/decode-vertex-format.ts
2995
- function getVertexFormatInfo(format) {
2996
- let webglOnly;
2997
- if (format.endsWith("-webgl")) {
2998
- format.replace("-webgl", "");
2999
- webglOnly = true;
3000
- }
3001
- const [type_, count] = format.split("x");
3002
- const type = type_;
3003
- const components = count ? parseInt(count) : 1;
3004
- const decodedType = getDataTypeInfo(type);
3005
- const result = {
3006
- type,
3007
- components,
3008
- byteLength: decodedType.byteLength * components,
3009
- integer: decodedType.integer,
3010
- signed: decodedType.signed,
3011
- normalized: decodedType.normalized
3012
- };
3013
- if (webglOnly) {
3014
- result.webglOnly = true;
3015
- }
3016
- return result;
3017
- }
3018
- function makeVertexFormat(signedDataType, components, normalized) {
3019
- const dataType = normalized ? makeNormalizedDataType(signedDataType) : signedDataType;
3020
- switch (dataType) {
3021
- case "unorm8":
3022
- if (components === 1) {
3023
- return "unorm8-webgl";
3024
- }
3025
- if (components === 3) {
3026
- return "unorm8x3-webgl";
3027
- }
3028
- return `${dataType}x${components}`;
3029
- case "snorm8":
3030
- case "uint8":
3031
- case "sint8":
3032
- case "uint16":
3033
- case "sint16":
3034
- case "unorm16":
3035
- case "snorm16":
3036
- case "float16":
3037
- if (components === 1 || components === 3) {
3038
- throw new Error(`size: ${components}`);
3039
- }
3040
- return `${dataType}x${components}`;
3041
- default:
3042
- return components === 1 ? dataType : `${dataType}x${components}`;
3043
- }
3044
- }
3045
- function getVertexFormatFromAttribute(typedArray, size, normalized) {
3046
- if (!size || size > 4) {
3047
- throw new Error(`size ${size}`);
3048
- }
3049
- const components = size;
3050
- const signedDataType = getDataTypeFromTypedArray(typedArray);
3051
- return makeVertexFormat(signedDataType, components, normalized);
3052
- }
3053
- function getCompatibleVertexFormat(opts) {
3054
- let vertexType;
3055
- switch (opts.primitiveType) {
3056
- case "f32":
3057
- vertexType = "float32";
3058
- break;
3059
- case "i32":
3060
- vertexType = "sint32";
3061
- break;
3062
- case "u32":
3063
- vertexType = "uint32";
3064
- break;
3065
- case "f16":
3066
- return opts.components <= 2 ? "float16x2" : "float16x4";
3067
- }
3068
- if (opts.components === 1) {
3069
- return vertexType;
3070
- }
3071
- return `${vertexType}x${opts.components}`;
3072
- }
3073
-
3074
3151
  // ../core/src/adapter-utils/get-attribute-from-layouts.ts
3075
3152
  function getAttributeInfosFromLayouts(shaderLayout, bufferLayout) {
3076
3153
  const attributeInfos = {};
@@ -3216,7 +3293,7 @@ ${htmlLog}
3216
3293
  // DEPRECATED METHODS
3217
3294
  /** @deprecated Set constant attributes (WebGL only) */
3218
3295
  setConstantWebGL(location, value) {
3219
- throw new Error("constant attributes not supported");
3296
+ this.device.reportError(new Error("constant attributes not supported"), this)();
3220
3297
  }
3221
3298
  };
3222
3299
  var VertexArray = _VertexArray;
@@ -3258,6 +3335,24 @@ ${htmlLog}
3258
3335
  count: void 0
3259
3336
  });
3260
3337
 
3338
+ // ../core/src/adapter/resources/pipeline-layout.ts
3339
+ var _PipelineLayout = class extends Resource {
3340
+ get [Symbol.toStringTag]() {
3341
+ return "PipelineLayout";
3342
+ }
3343
+ constructor(device, props) {
3344
+ super(device, props, _PipelineLayout.defaultProps);
3345
+ }
3346
+ };
3347
+ var PipelineLayout = _PipelineLayout;
3348
+ __publicField(PipelineLayout, "defaultProps", {
3349
+ ...Resource.defaultProps,
3350
+ shaderLayout: {
3351
+ attributes: [],
3352
+ bindings: []
3353
+ }
3354
+ });
3355
+
3261
3356
  // ../core/src/utils/array-utils-flat.ts
3262
3357
  var arrayBuffer;
3263
3358
  function getScratchArrayBuffer(byteLength) {
@@ -3541,32 +3636,87 @@ ${htmlLog}
3541
3636
  }
3542
3637
  };
3543
3638
 
3544
- // ../core/src/adapter-utils/buffer-layout-helper.ts
3545
- var BufferLayoutHelper = class {
3546
- bufferLayouts;
3547
- constructor(bufferLayouts) {
3548
- this.bufferLayouts = bufferLayouts;
3549
- }
3550
- getBufferLayout(name2) {
3551
- return this.bufferLayouts.find((layout) => layout.name === name2) || null;
3552
- }
3553
- /** Get attribute names from a BufferLayout */
3554
- getAttributeNamesForBuffer(bufferLayout) {
3555
- return bufferLayout.attributes ? bufferLayout.attributes?.map((layout) => layout.attribute) : [bufferLayout.name];
3556
- }
3557
- mergeBufferLayouts(bufferLayouts1, bufferLayouts2) {
3558
- const mergedLayouts = [...bufferLayouts1];
3559
- for (const attribute of bufferLayouts2) {
3560
- const index = mergedLayouts.findIndex((attribute2) => attribute2.name === attribute.name);
3561
- if (index < 0) {
3562
- mergedLayouts.push(attribute);
3563
- } else {
3564
- mergedLayouts[index] = attribute;
3565
- }
3639
+ // ../core/src/shadertypes/textures/pixel-utils.ts
3640
+ function readPixel(pixelData, x, y, bitsPerChannel) {
3641
+ if (x < 0 || x >= pixelData.width || y < 0 || y >= pixelData.height) {
3642
+ throw new Error("Coordinates out of bounds.");
3643
+ }
3644
+ const byteOffset = y * pixelData.bytesPerRow + x * pixelData.bytesPerPixel;
3645
+ const pixelDataView = new DataView(pixelData.arrayBuffer, byteOffset, pixelData.bytesPerPixel);
3646
+ let bitOffsetWithinPixel = 0;
3647
+ const channels = [];
3648
+ for (let i = 0; i < 4; i++) {
3649
+ const bits = bitsPerChannel[i];
3650
+ if (bits <= 0) {
3651
+ channels.push(0);
3652
+ } else {
3653
+ const channelValue = readBitsFromDataView(pixelDataView, bitOffsetWithinPixel, bits);
3654
+ channels.push(channelValue);
3655
+ bitOffsetWithinPixel += bits;
3656
+ }
3657
+ }
3658
+ return [channels[0], channels[1], channels[2], channels[3]];
3659
+ }
3660
+ function writePixel(dataView, bitOffset, bitsPerChannel, pixel) {
3661
+ let currentBitOffset = bitOffset;
3662
+ for (let channel = 0; channel < 4; channel++) {
3663
+ const bits = bitsPerChannel[channel];
3664
+ const maxValue = (1 << bits) - 1;
3665
+ const channelValue = pixel[channel] & maxValue;
3666
+ writeBitsToDataView(dataView, currentBitOffset, bits, channelValue);
3667
+ currentBitOffset += bits;
3668
+ }
3669
+ }
3670
+ function readBitsFromDataView(dataView, bitOffset, bitCount) {
3671
+ if (bitOffset % 8 === 0) {
3672
+ const byteOffset = bitOffset / 8;
3673
+ if (bitCount === 8 && byteOffset + 1 <= dataView.byteLength) {
3674
+ return dataView.getUint8(byteOffset);
3675
+ } else if (bitCount === 16 && byteOffset + 2 <= dataView.byteLength) {
3676
+ return dataView.getUint16(byteOffset, false);
3677
+ } else if (bitCount === 32 && byteOffset + 4 <= dataView.byteLength) {
3678
+ return dataView.getUint32(byteOffset, false);
3679
+ }
3680
+ }
3681
+ let value = 0;
3682
+ for (let i = 0; i < bitCount; i++) {
3683
+ const overallBitIndex = bitOffset + i;
3684
+ const byteIndex = Math.floor(overallBitIndex / 8);
3685
+ const bitIndex = overallBitIndex % 8;
3686
+ const byteValue = dataView.getUint8(byteIndex);
3687
+ const bit = byteValue >> 7 - bitIndex & 1;
3688
+ value = value << 1 | bit;
3689
+ }
3690
+ return value;
3691
+ }
3692
+ function writeBitsToDataView(dataView, bitOffset, bitCount, value) {
3693
+ if (bitOffset % 8 === 0) {
3694
+ const byteOffset = bitOffset / 8;
3695
+ if (bitCount === 8 && byteOffset + 1 <= dataView.byteLength) {
3696
+ dataView.setUint8(byteOffset, value & 255);
3697
+ return;
3698
+ } else if (bitCount === 16 && byteOffset + 2 <= dataView.byteLength) {
3699
+ dataView.setUint16(byteOffset, value & 65535, false);
3700
+ return;
3701
+ } else if (bitCount === 32 && byteOffset + 4 <= dataView.byteLength) {
3702
+ dataView.setUint32(byteOffset, value, false);
3703
+ return;
3566
3704
  }
3567
- return mergedLayouts;
3568
3705
  }
3569
- };
3706
+ for (let i = 0; i < bitCount; i++) {
3707
+ const overallBitIndex = bitOffset + i;
3708
+ const byteIndex = Math.floor(overallBitIndex / 8);
3709
+ const bitIndex = overallBitIndex % 8;
3710
+ const mask = 1 << 7 - bitIndex;
3711
+ const bitValue = value >> bitCount - 1 - i & 1;
3712
+ let currentByte = dataView.getUint8(byteIndex);
3713
+ currentByte &= ~mask;
3714
+ if (bitValue) {
3715
+ currentByte |= mask;
3716
+ }
3717
+ dataView.setUint8(byteIndex, currentByte);
3718
+ }
3719
+ }
3570
3720
 
3571
3721
  // bundle.ts
3572
3722
  __reExport(bundle_exports, __toESM(require_shadertools(), 1));