@luma.gl/webgl 9.0.0-alpha.26 → 9.0.0-alpha.27

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
@@ -1851,6 +1851,7 @@ var __exports__ = (() => {
1851
1851
  };
1852
1852
  /** Set attributes (stored on pipeline and set before each call) */
1853
1853
  /** Set attributes (stored on pipeline and set before each call) */
1854
+ /** Set constant attributes (WebGL only) */
1854
1855
  /** Set bindings (stored on pipeline and set before each call) */
1855
1856
  /** Uniforms (only supported on WebGL devices. Reset before each call to enable pipeline sharing) */
1856
1857
  /** Draw call */
@@ -2256,6 +2257,43 @@ var __exports__ = (() => {
2256
2257
  });
2257
2258
  }
2258
2259
 
2260
+ // ../api/src/lib/utils/array-utils-flat.ts
2261
+ var arrayBuffer;
2262
+ function getScratchArrayBuffer(byteLength) {
2263
+ if (!arrayBuffer || arrayBuffer.byteLength < byteLength) {
2264
+ arrayBuffer = new ArrayBuffer(byteLength);
2265
+ }
2266
+ return arrayBuffer;
2267
+ }
2268
+ function getScratchArray(Type, length) {
2269
+ const scratchArrayBuffer = getScratchArrayBuffer(Type.BYTES_PER_ELEMENT * length);
2270
+ return new Type(scratchArrayBuffer, 0, length);
2271
+ }
2272
+ function fillArray(options) {
2273
+ const {
2274
+ target,
2275
+ source,
2276
+ start = 0,
2277
+ count = 1
2278
+ } = options;
2279
+ const length = source.length;
2280
+ const total = count * length;
2281
+ let copied = 0;
2282
+ for (let i = start; copied < length; copied++) {
2283
+ target[i++] = source[copied];
2284
+ }
2285
+ while (copied < total) {
2286
+ if (copied < total - copied) {
2287
+ target.copyWithin(start + copied, start, start + copied);
2288
+ copied *= 2;
2289
+ } else {
2290
+ target.copyWithin(start + copied, start, start + total - copied);
2291
+ copied = total;
2292
+ }
2293
+ }
2294
+ return options.target;
2295
+ }
2296
+
2259
2297
  // src/context/polyfill/polyfill-vertex-array-object.ts
2260
2298
  var glErrorShadow = {};
2261
2299
  function error(msg) {
@@ -8646,8 +8684,25 @@ ${formattedLog}`)();
8646
8684
  get [Symbol.toStringTag]() {
8647
8685
  return "BaseVertexArrayObject";
8648
8686
  }
8687
+ /** Buffer constant */
8688
+ buffer = null;
8689
+ bufferValue = null;
8690
+ static isConstantAttributeZeroSupported(device) {
8691
+ return device.info.type === "webgl2" || getBrowser() === "Chrome";
8692
+ }
8693
+ // Create a VertexArray
8649
8694
  constructor(device, props) {
8650
- super(device, props, {});
8695
+ super(device, props, {
8696
+ ...Resource.defaultProps,
8697
+ constantAttributeZero: false
8698
+ });
8699
+ Object.seal(this);
8700
+ }
8701
+ destroy() {
8702
+ super.destroy();
8703
+ if (this.buffer) {
8704
+ this.buffer?.destroy();
8705
+ }
8651
8706
  }
8652
8707
  _createHandle() {
8653
8708
  return this.gl2.createVertexArray();
@@ -8659,6 +8714,20 @@ ${formattedLog}`)();
8659
8714
  _bindHandle(handle) {
8660
8715
  this.gl2.bindVertexArray(handle);
8661
8716
  }
8717
+ /**
8718
+ * Enabling an attribute location makes it reference the currently bound buffer
8719
+ * Disabling an attribute location makes it reference the global constant value
8720
+ * TODO - handle single values for size 1 attributes?
8721
+ * TODO - convert classic arrays based on known type?
8722
+ */
8723
+ enable(location, enable2 = true) {
8724
+ const canDisableAttributeZero = this.device.isWebGL2 || getBrowser() === "Chrome";
8725
+ const canDisableAttribute = canDisableAttributeZero || location !== 0;
8726
+ if (enable2 || canDisableAttribute) {
8727
+ location = Number(location);
8728
+ this.bind(() => enable2 ? this.gl.enableVertexAttribArray(location) : this.gl.disableVertexAttribArray(location));
8729
+ }
8730
+ }
8662
8731
  // Set (bind) an elements buffer, for indexed rendering.
8663
8732
  // Must be a Buffer bound to GL.ELEMENT_ARRAY_BUFFER. Constants not supported
8664
8733
  setElementBuffer(elementBuffer = null, opts = {}) {
@@ -8666,12 +8735,12 @@ ${formattedLog}`)();
8666
8735
  this.bind(() => {
8667
8736
  this.gl.bindBuffer(GL.ELEMENT_ARRAY_BUFFER, elementBuffer ? elementBuffer.handle : null);
8668
8737
  });
8669
- return this;
8670
8738
  }
8671
8739
  /** Set a location in vertex attributes array to a buffer, enables the location, sets divisor */
8672
8740
  setBuffer(location, buffer, accessor) {
8673
8741
  if (buffer.target === GL.ELEMENT_ARRAY_BUFFER) {
8674
- return this.setElementBuffer(buffer, accessor);
8742
+ this.setElementBuffer(buffer, accessor);
8743
+ return;
8675
8744
  }
8676
8745
  const {
8677
8746
  size,
@@ -8698,24 +8767,106 @@ ${formattedLog}`)();
8698
8767
  gl2.enableVertexAttribArray(location);
8699
8768
  gl22.vertexAttribDivisor(location, divisor || 0);
8700
8769
  });
8701
- return this;
8702
8770
  }
8703
8771
  /**
8704
- * Enabling an attribute location makes it reference the currently bound buffer
8705
- * Disabling an attribute location makes it reference the global constant value
8706
- * TODO - handle single values for size 1 attributes?
8707
- * TODO - convert classic arrays based on known type?
8772
+ * Set an attribute to a constant value
8773
+ * @param device
8774
+ * @param location
8775
+ * @param array
8776
+ *
8777
+ * @note Constants are stored globally on the WebGL context, not the VAO
8778
+ * so they need to be updated before every render
8779
+ * @todo - use known type (in configuration or passed in) to allow non-typed arrays?
8780
+ * @todo - remember/cache values to avoid setting them unnecessarily?
8708
8781
  */
8709
- enable(location, enable2 = true) {
8710
- const canDisableAttributeZero = this.device.isWebGL2 || getBrowser() === "Chrome";
8711
- const canDisableAttribute = canDisableAttributeZero || location !== 0;
8712
- if (enable2 || canDisableAttribute) {
8713
- location = Number(location);
8714
- this.bind(() => enable2 ? this.gl.enableVertexAttribArray(location) : this.gl.disableVertexAttribArray(location));
8782
+ setConstant(location, array) {
8783
+ switch (array.constructor) {
8784
+ case Float32Array:
8785
+ setConstantFloatArray(this.device, location, array);
8786
+ break;
8787
+ case Int32Array:
8788
+ setConstantIntArray(this.device, location, array);
8789
+ break;
8790
+ case Uint32Array:
8791
+ setConstantUintArray(this.device, location, array);
8792
+ break;
8793
+ default:
8794
+ assert2(false);
8715
8795
  }
8716
- return this;
8796
+ }
8797
+ /**
8798
+ * Provide a means to create a buffer that is equivalent to a constant.
8799
+ * NOTE: Desktop OpenGL cannot disable attribute 0.
8800
+ * https://stackoverflow.com/questions/20305231/webgl-warning-attribute-0-is-disabled-
8801
+ * this-has-significant-performance-penalty
8802
+ */
8803
+ getConstantBuffer(elementCount, value) {
8804
+ const constantValue = normalizeConstantArrayValue(value);
8805
+ const byteLength = constantValue.byteLength * elementCount;
8806
+ const length = constantValue.length * elementCount;
8807
+ let updateNeeded = !this.buffer;
8808
+ this.buffer = this.buffer || this.device.createBuffer({
8809
+ byteLength
8810
+ });
8811
+ updateNeeded = updateNeeded || this.buffer.reallocate(byteLength);
8812
+ updateNeeded = updateNeeded || !compareConstantArrayValues(constantValue, this.bufferValue);
8813
+ if (updateNeeded) {
8814
+ const typedArray = getScratchArray(value.constructor, length);
8815
+ fillArray({
8816
+ target: typedArray,
8817
+ source: constantValue,
8818
+ start: 0,
8819
+ count: length
8820
+ });
8821
+ this.buffer.subData(typedArray);
8822
+ this.bufferValue = value;
8823
+ }
8824
+ return this.buffer;
8717
8825
  }
8718
8826
  };
8827
+ function setConstantFloatArray(device, location, array) {
8828
+ switch (array.length) {
8829
+ case 1:
8830
+ device.gl.vertexAttrib1fv(location, array);
8831
+ break;
8832
+ case 2:
8833
+ device.gl.vertexAttrib2fv(location, array);
8834
+ break;
8835
+ case 3:
8836
+ device.gl.vertexAttrib3fv(location, array);
8837
+ break;
8838
+ case 4:
8839
+ device.gl.vertexAttrib4fv(location, array);
8840
+ break;
8841
+ default:
8842
+ assert2(false);
8843
+ }
8844
+ }
8845
+ function setConstantIntArray(device, location, array) {
8846
+ device.assertWebGL2();
8847
+ device.gl2?.vertexAttribI4iv(location, array);
8848
+ }
8849
+ function setConstantUintArray(device, location, array) {
8850
+ device.assertWebGL2();
8851
+ device.gl2?.vertexAttribI4uiv(location, array);
8852
+ }
8853
+ function normalizeConstantArrayValue(arrayValue) {
8854
+ if (Array.isArray(arrayValue)) {
8855
+ return new Float32Array(arrayValue);
8856
+ }
8857
+ return arrayValue;
8858
+ }
8859
+ function compareConstantArrayValues(v1, v2) {
8860
+ if (!v1 || !v2 || v1.length !== v2.length || v1.constructor !== v2.constructor) {
8861
+ return false;
8862
+ }
8863
+ for (let i = 0; i < v1.length; ++i) {
8864
+ if (v1[i] !== v2[i]) {
8865
+ return false;
8866
+ }
8867
+ }
8868
+ return true;
8869
+ }
8719
8870
 
8720
8871
  // src/adapter/resources/webgl-render-pipeline.ts
8721
8872
  var LOG_PROGRAM_PERF_PRIORITY = 4;
@@ -8793,7 +8944,26 @@ ${formattedLog}`)();
8793
8944
  });
8794
8945
  }
8795
8946
  }
8796
- /** @todo needed for portable model */
8947
+ /**
8948
+ * Constant attributes are only supported in WebGL, not in WebGPU
8949
+ * Any attribute that is disabled in the current vertex array object
8950
+ * is read from the context's global constant value for that attribute location.
8951
+ * @param attributes
8952
+ */
8953
+ setConstantAttributes(attributes) {
8954
+ for (const [name, value] of Object.entries(attributes)) {
8955
+ const attribute = getAttributeLayout(this.layout, name);
8956
+ if (!attribute) {
8957
+ log.warn(`Ignoring constant value supplied for unknown attribute "${name}" in pipeline "${this.id}"`)();
8958
+ continue;
8959
+ }
8960
+ this.vertexArrayObject.setConstant(attribute.location, value);
8961
+ }
8962
+ }
8963
+ /**
8964
+ * Bindings include: textures, samplers and uniform buffers
8965
+ * @todo needed for portable model
8966
+ */
8797
8967
  setBindings(bindings) {
8798
8968
  for (const [name, value] of Object.entries(bindings)) {
8799
8969
  const binding = this.layout.bindings.find((binding2) => binding2.name === name);
package/dist/index.cjs CHANGED
@@ -5236,11 +5236,26 @@ var import_constants24 = require("@luma.gl/constants");
5236
5236
  var import_env = require("@probe.gl/env");
5237
5237
  var ERR_ELEMENTS = "elements must be GL.ELEMENT_ARRAY_BUFFER";
5238
5238
  var WEBGLVertexArrayObject = class extends WebGLResource {
5239
+ // Create a VertexArray
5240
+ constructor(device, props) {
5241
+ super(device, props, __spreadProps(__spreadValues({}, import_api22.Resource.defaultProps), { constantAttributeZero: false }));
5242
+ /** Buffer constant */
5243
+ this.buffer = null;
5244
+ this.bufferValue = null;
5245
+ Object.seal(this);
5246
+ }
5239
5247
  get [Symbol.toStringTag]() {
5240
5248
  return "BaseVertexArrayObject";
5241
5249
  }
5242
- constructor(device, props) {
5243
- super(device, props, {});
5250
+ static isConstantAttributeZeroSupported(device) {
5251
+ return device.info.type === "webgl2" || (0, import_env.getBrowser)() === "Chrome";
5252
+ }
5253
+ destroy() {
5254
+ var _a;
5255
+ super.destroy();
5256
+ if (this.buffer) {
5257
+ (_a = this.buffer) == null ? void 0 : _a.destroy();
5258
+ }
5244
5259
  }
5245
5260
  _createHandle() {
5246
5261
  return this.gl2.createVertexArray();
@@ -5252,6 +5267,22 @@ var WEBGLVertexArrayObject = class extends WebGLResource {
5252
5267
  _bindHandle(handle) {
5253
5268
  this.gl2.bindVertexArray(handle);
5254
5269
  }
5270
+ /**
5271
+ * Enabling an attribute location makes it reference the currently bound buffer
5272
+ * Disabling an attribute location makes it reference the global constant value
5273
+ * TODO - handle single values for size 1 attributes?
5274
+ * TODO - convert classic arrays based on known type?
5275
+ */
5276
+ enable(location, enable2 = true) {
5277
+ const canDisableAttributeZero = this.device.isWebGL2 || (0, import_env.getBrowser)() === "Chrome";
5278
+ const canDisableAttribute = canDisableAttributeZero || location !== 0;
5279
+ if (enable2 || canDisableAttribute) {
5280
+ location = Number(location);
5281
+ this.bind(
5282
+ () => enable2 ? this.gl.enableVertexAttribArray(location) : this.gl.disableVertexAttribArray(location)
5283
+ );
5284
+ }
5285
+ }
5255
5286
  // Set (bind) an elements buffer, for indexed rendering.
5256
5287
  // Must be a Buffer bound to GL.ELEMENT_ARRAY_BUFFER. Constants not supported
5257
5288
  setElementBuffer(elementBuffer = null, opts = {}) {
@@ -5259,12 +5290,12 @@ var WEBGLVertexArrayObject = class extends WebGLResource {
5259
5290
  this.bind(() => {
5260
5291
  this.gl.bindBuffer(import_constants24.GL.ELEMENT_ARRAY_BUFFER, elementBuffer ? elementBuffer.handle : null);
5261
5292
  });
5262
- return this;
5263
5293
  }
5264
5294
  /** Set a location in vertex attributes array to a buffer, enables the location, sets divisor */
5265
5295
  setBuffer(location, buffer, accessor) {
5266
5296
  if (buffer.target === import_constants24.GL.ELEMENT_ARRAY_BUFFER) {
5267
- return this.setElementBuffer(buffer, accessor);
5297
+ this.setElementBuffer(buffer, accessor);
5298
+ return;
5268
5299
  }
5269
5300
  const { size, type, stride, offset, normalized, integer, divisor } = accessor;
5270
5301
  const { gl: gl2, gl2: gl22 } = this;
@@ -5280,26 +5311,101 @@ var WEBGLVertexArrayObject = class extends WebGLResource {
5280
5311
  gl2.enableVertexAttribArray(location);
5281
5312
  gl22.vertexAttribDivisor(location, divisor || 0);
5282
5313
  });
5283
- return this;
5284
5314
  }
5285
5315
  /**
5286
- * Enabling an attribute location makes it reference the currently bound buffer
5287
- * Disabling an attribute location makes it reference the global constant value
5288
- * TODO - handle single values for size 1 attributes?
5289
- * TODO - convert classic arrays based on known type?
5316
+ * Set an attribute to a constant value
5317
+ * @param device
5318
+ * @param location
5319
+ * @param array
5320
+ *
5321
+ * @note Constants are stored globally on the WebGL context, not the VAO
5322
+ * so they need to be updated before every render
5323
+ * @todo - use known type (in configuration or passed in) to allow non-typed arrays?
5324
+ * @todo - remember/cache values to avoid setting them unnecessarily?
5290
5325
  */
5291
- enable(location, enable2 = true) {
5292
- const canDisableAttributeZero = this.device.isWebGL2 || (0, import_env.getBrowser)() === "Chrome";
5293
- const canDisableAttribute = canDisableAttributeZero || location !== 0;
5294
- if (enable2 || canDisableAttribute) {
5295
- location = Number(location);
5296
- this.bind(
5297
- () => enable2 ? this.gl.enableVertexAttribArray(location) : this.gl.disableVertexAttribArray(location)
5298
- );
5326
+ setConstant(location, array) {
5327
+ switch (array.constructor) {
5328
+ case Float32Array:
5329
+ setConstantFloatArray(this.device, location, array);
5330
+ break;
5331
+ case Int32Array:
5332
+ setConstantIntArray(this.device, location, array);
5333
+ break;
5334
+ case Uint32Array:
5335
+ setConstantUintArray(this.device, location, array);
5336
+ break;
5337
+ default:
5338
+ (0, import_api22.assert)(false);
5299
5339
  }
5300
- return this;
5340
+ }
5341
+ /**
5342
+ * Provide a means to create a buffer that is equivalent to a constant.
5343
+ * NOTE: Desktop OpenGL cannot disable attribute 0.
5344
+ * https://stackoverflow.com/questions/20305231/webgl-warning-attribute-0-is-disabled-
5345
+ * this-has-significant-performance-penalty
5346
+ */
5347
+ getConstantBuffer(elementCount, value) {
5348
+ const constantValue = normalizeConstantArrayValue(value);
5349
+ const byteLength = constantValue.byteLength * elementCount;
5350
+ const length = constantValue.length * elementCount;
5351
+ let updateNeeded = !this.buffer;
5352
+ this.buffer = this.buffer || this.device.createBuffer({ byteLength });
5353
+ updateNeeded = updateNeeded || this.buffer.reallocate(byteLength);
5354
+ updateNeeded = updateNeeded || !compareConstantArrayValues(constantValue, this.bufferValue);
5355
+ if (updateNeeded) {
5356
+ const typedArray = (0, import_api22.getScratchArray)(value.constructor, length);
5357
+ (0, import_api22.fillArray)({ target: typedArray, source: constantValue, start: 0, count: length });
5358
+ this.buffer.subData(typedArray);
5359
+ this.bufferValue = value;
5360
+ }
5361
+ return this.buffer;
5301
5362
  }
5302
5363
  };
5364
+ function setConstantFloatArray(device, location, array) {
5365
+ switch (array.length) {
5366
+ case 1:
5367
+ device.gl.vertexAttrib1fv(location, array);
5368
+ break;
5369
+ case 2:
5370
+ device.gl.vertexAttrib2fv(location, array);
5371
+ break;
5372
+ case 3:
5373
+ device.gl.vertexAttrib3fv(location, array);
5374
+ break;
5375
+ case 4:
5376
+ device.gl.vertexAttrib4fv(location, array);
5377
+ break;
5378
+ default:
5379
+ (0, import_api22.assert)(false);
5380
+ }
5381
+ }
5382
+ function setConstantIntArray(device, location, array) {
5383
+ var _a;
5384
+ device.assertWebGL2();
5385
+ (_a = device.gl2) == null ? void 0 : _a.vertexAttribI4iv(location, array);
5386
+ }
5387
+ function setConstantUintArray(device, location, array) {
5388
+ var _a;
5389
+ device.assertWebGL2();
5390
+ (_a = device.gl2) == null ? void 0 : _a.vertexAttribI4uiv(location, array);
5391
+ }
5392
+ function normalizeConstantArrayValue(arrayValue) {
5393
+ if (Array.isArray(arrayValue)) {
5394
+ return new Float32Array(arrayValue);
5395
+ }
5396
+ return arrayValue;
5397
+ }
5398
+ function compareConstantArrayValues(v1, v2) {
5399
+ if (!v1 || !v2 || v1.length !== v2.length || v1.constructor !== v2.constructor) {
5400
+ return false;
5401
+ }
5402
+ for (let i = 0; i < v1.length; ++i) {
5403
+ if (v1[i] !== v2[i]) {
5404
+ return false;
5405
+ }
5406
+ }
5407
+ return true;
5408
+ }
5303
5409
 
5304
5410
  // src/adapter/resources/webgl-render-pipeline.ts
5305
5411
  var LOG_PROGRAM_PERF_PRIORITY = 4;
@@ -5367,7 +5473,26 @@ var WEBGLRenderPipeline = class extends import_api23.RenderPipeline {
5367
5473
  });
5368
5474
  }
5369
5475
  }
5370
- /** @todo needed for portable model */
5476
+ /**
5477
+ * Constant attributes are only supported in WebGL, not in WebGPU
5478
+ * Any attribute that is disabled in the current vertex array object
5479
+ * is read from the context's global constant value for that attribute location.
5480
+ * @param attributes
5481
+ */
5482
+ setConstantAttributes(attributes) {
5483
+ for (const [name, value] of Object.entries(attributes)) {
5484
+ const attribute = getAttributeLayout(this.layout, name);
5485
+ if (!attribute) {
5486
+ import_api23.log.warn(`Ignoring constant value supplied for unknown attribute "${name}" in pipeline "${this.id}"`)();
5487
+ continue;
5488
+ }
5489
+ this.vertexArrayObject.setConstant(attribute.location, value);
5490
+ }
5491
+ }
5492
+ /**
5493
+ * Bindings include: textures, samplers and uniform buffers
5494
+ * @todo needed for portable model
5495
+ */
5371
5496
  setBindings(bindings) {
5372
5497
  for (const [name, value] of Object.entries(bindings)) {
5373
5498
  const binding = this.layout.bindings.find((binding2) => binding2.name === name);