@deck.gl/arcgis 9.4.0-beta.1 → 9.4.0-beta.4

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
@@ -3213,245 +3213,6 @@ Source: ${sourceLine}` : "";
3213
3213
  }
3214
3214
  });
3215
3215
 
3216
- // ../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-render-pipeline.js
3217
- function mergeShaderLayout(baseLayout, overrideLayout) {
3218
- const mergedLayout = {
3219
- ...baseLayout,
3220
- attributes: baseLayout.attributes.map((attribute) => ({ ...attribute })),
3221
- bindings: baseLayout.bindings.map((binding) => ({ ...binding }))
3222
- };
3223
- for (const attribute of overrideLayout?.attributes || []) {
3224
- const baseAttribute = mergedLayout.attributes.find((attr) => attr.name === attribute.name);
3225
- if (!baseAttribute) {
3226
- import_core15.log.warn(`shader layout attribute ${attribute.name} not present in shader`);
3227
- } else {
3228
- baseAttribute.type = attribute.type || baseAttribute.type;
3229
- baseAttribute.stepMode = attribute.stepMode || baseAttribute.stepMode;
3230
- }
3231
- }
3232
- for (const binding of overrideLayout?.bindings || []) {
3233
- const baseBinding = getShaderLayoutBindingByName(mergedLayout, binding.name);
3234
- if (!baseBinding) {
3235
- import_core15.log.warn(`shader layout binding ${binding.name} not present in shader`);
3236
- continue;
3237
- }
3238
- Object.assign(baseBinding, binding);
3239
- }
3240
- return mergedLayout;
3241
- }
3242
- function getShaderLayoutBindingByName(shaderLayout, bindingName) {
3243
- return shaderLayout.bindings.find((binding) => binding.name === bindingName || binding.name === `${bindingName}Uniforms` || `${binding.name}Uniforms` === bindingName);
3244
- }
3245
- function getBindingValueForLayoutBinding(bindings, bindingName) {
3246
- return bindings[bindingName] || bindings[`${bindingName}Uniforms`] || bindings[bindingName.replace(/Uniforms$/, "")];
3247
- }
3248
- var import_core15, WEBGLRenderPipeline;
3249
- var init_webgl_render_pipeline = __esm({
3250
- "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-render-pipeline.js"() {
3251
- import_core15 = __toESM(require_core2(), 1);
3252
- init_set_uniform();
3253
- init_webgl_buffer();
3254
- init_webgl_framebuffer();
3255
- init_webgl_texture();
3256
- init_webgl_texture_view();
3257
- WEBGLRenderPipeline = class extends import_core15.RenderPipeline {
3258
- /** The WebGL device that created this render pipeline */
3259
- device;
3260
- /** Handle to underlying WebGL program */
3261
- handle;
3262
- /** vertex shader */
3263
- vs;
3264
- /** fragment shader */
3265
- fs;
3266
- /** The layout extracted from shader by WebGL introspection APIs */
3267
- introspectedLayout;
3268
- /** Compatibility path for direct pipeline.setBindings() usage */
3269
- bindings = {};
3270
- /** Compatibility path for direct pipeline.uniforms usage */
3271
- uniforms = {};
3272
- /** WebGL varyings */
3273
- varyings = null;
3274
- _uniformCount = 0;
3275
- _uniformSetters = {};
3276
- // TODO are these used?
3277
- get [Symbol.toStringTag]() {
3278
- return "WEBGLRenderPipeline";
3279
- }
3280
- constructor(device, props) {
3281
- super(device, props);
3282
- this.device = device;
3283
- const webglSharedRenderPipeline = this.sharedRenderPipeline || this.device._createSharedRenderPipelineWebGL(props);
3284
- this.sharedRenderPipeline = webglSharedRenderPipeline;
3285
- this.handle = webglSharedRenderPipeline.handle;
3286
- this.vs = webglSharedRenderPipeline.vs;
3287
- this.fs = webglSharedRenderPipeline.fs;
3288
- this.linkStatus = webglSharedRenderPipeline.linkStatus;
3289
- this.introspectedLayout = webglSharedRenderPipeline.introspectedLayout;
3290
- this.device._setWebGLDebugMetadata(this.handle, this, { spector: { id: this.props.id } });
3291
- this.shaderLayout = props.shaderLayout ? mergeShaderLayout(this.introspectedLayout, props.shaderLayout) : this.introspectedLayout;
3292
- }
3293
- destroy() {
3294
- if (this.destroyed) {
3295
- return;
3296
- }
3297
- if (this.sharedRenderPipeline && !this.props._sharedRenderPipeline) {
3298
- this.sharedRenderPipeline.destroy();
3299
- }
3300
- this.destroyResource();
3301
- }
3302
- /** @deprecated Set bindings on RenderPass instead. Will be removed in the next major release. */
3303
- setBindings(bindings, options) {
3304
- const flatBindings = (0, import_core15.flattenBindingsByGroup)((0, import_core15.normalizeBindingsByGroup)(this.shaderLayout, bindings));
3305
- for (const [name, value] of Object.entries(flatBindings)) {
3306
- const binding = getShaderLayoutBindingByName(this.shaderLayout, name);
3307
- if (!binding) {
3308
- const validBindings = this.shaderLayout.bindings.map((binding_) => `"${binding_.name}"`).join(", ");
3309
- if (!options?.disableWarnings) {
3310
- import_core15.log.warn(`No binding "${name}" in render pipeline "${this.id}", expected one of ${validBindings}`, value)();
3311
- }
3312
- } else {
3313
- if (!value) {
3314
- import_core15.log.warn(`Unsetting binding "${name}" in render pipeline "${this.id}"`)();
3315
- }
3316
- switch (binding.type) {
3317
- case "uniform":
3318
- if (!(value instanceof WEBGLBuffer) && !(value.buffer instanceof WEBGLBuffer)) {
3319
- throw new Error("buffer value");
3320
- }
3321
- break;
3322
- case "texture":
3323
- if (!(value instanceof WEBGLTextureView || value instanceof WEBGLTexture || value instanceof WEBGLFramebuffer)) {
3324
- throw new Error(`${this} Bad texture binding for ${name}`);
3325
- }
3326
- break;
3327
- case "sampler":
3328
- import_core15.log.warn(`Ignoring sampler ${name}`)();
3329
- break;
3330
- default:
3331
- throw new Error(binding.type);
3332
- }
3333
- this.bindings[name] = value;
3334
- }
3335
- }
3336
- }
3337
- /** @todo needed for portable model
3338
- * @note The WebGL API is offers many ways to draw things
3339
- * This function unifies those ways into a single call using common parameters with sane defaults
3340
- */
3341
- draw(options) {
3342
- const webglRenderPass = options.renderPass;
3343
- const drawBindings = options.bindGroups ? (0, import_core15.flattenBindingsByGroup)(options.bindGroups) : options.bindings || this.bindings;
3344
- webglRenderPass.setPipeline(this);
3345
- webglRenderPass.setBindings(drawBindings);
3346
- webglRenderPass.setVertexArray(options.vertexArray);
3347
- return webglRenderPass.draw({
3348
- parameters: options.parameters,
3349
- topology: options.topology,
3350
- isInstanced: options.isInstanced,
3351
- vertexCount: options.vertexCount,
3352
- indexCount: options.indexCount,
3353
- instanceCount: options.instanceCount,
3354
- firstVertex: options.firstVertex,
3355
- firstIndex: options.firstIndex,
3356
- firstInstance: options.firstInstance,
3357
- baseVertex: options.baseVertex,
3358
- transformFeedback: options.transformFeedback,
3359
- uniforms: options.uniforms
3360
- });
3361
- }
3362
- /**
3363
- * Checks if all texture-values uniforms are renderable (i.e. loaded)
3364
- * Update a texture if needed (e.g. from video)
3365
- * Note: This is currently done before every draw call
3366
- */
3367
- _areTexturesRenderable(bindings) {
3368
- let texturesRenderable = true;
3369
- for (const bindingInfo of this.shaderLayout.bindings) {
3370
- if (!getBindingValueForLayoutBinding(bindings, bindingInfo.name)) {
3371
- import_core15.log.warn(`Binding ${bindingInfo.name} not found in ${this.id}`)();
3372
- texturesRenderable = false;
3373
- }
3374
- }
3375
- return texturesRenderable;
3376
- }
3377
- /** Apply any bindings (before each draw call) */
3378
- _applyBindings(bindings, _options) {
3379
- this._syncLinkStatus();
3380
- if (this.linkStatus !== "success") {
3381
- return;
3382
- }
3383
- const { gl } = this.device;
3384
- gl.useProgram(this.handle);
3385
- let textureUnit = 0;
3386
- let uniformBufferIndex = 0;
3387
- for (const binding of this.shaderLayout.bindings) {
3388
- const value = getBindingValueForLayoutBinding(bindings, binding.name);
3389
- if (!value) {
3390
- throw new Error(`No value for binding ${binding.name} in ${this.id}`);
3391
- }
3392
- switch (binding.type) {
3393
- case "uniform":
3394
- const { name } = binding;
3395
- const location = gl.getUniformBlockIndex(this.handle, name);
3396
- if (location === 4294967295) {
3397
- throw new Error(`Invalid uniform block name ${name}`);
3398
- }
3399
- gl.uniformBlockBinding(this.handle, location, uniformBufferIndex);
3400
- if (value instanceof WEBGLBuffer) {
3401
- gl.bindBufferBase(35345, uniformBufferIndex, value.handle);
3402
- } else {
3403
- const bufferBinding = value;
3404
- gl.bindBufferRange(35345, uniformBufferIndex, bufferBinding.buffer.handle, bufferBinding.offset || 0, bufferBinding.size || bufferBinding.buffer.byteLength - (bufferBinding.offset || 0));
3405
- }
3406
- uniformBufferIndex += 1;
3407
- break;
3408
- case "texture":
3409
- if (!(value instanceof WEBGLTextureView || value instanceof WEBGLTexture || value instanceof WEBGLFramebuffer)) {
3410
- throw new Error("texture");
3411
- }
3412
- let texture;
3413
- if (value instanceof WEBGLTextureView) {
3414
- texture = value.texture;
3415
- } else if (value instanceof WEBGLTexture) {
3416
- texture = value;
3417
- } else if (value instanceof WEBGLFramebuffer && value.colorAttachments[0] instanceof WEBGLTextureView) {
3418
- import_core15.log.warn("Passing framebuffer in texture binding may be deprecated. Use fbo.colorAttachments[0] instead")();
3419
- texture = value.colorAttachments[0].texture;
3420
- } else {
3421
- throw new Error("No texture");
3422
- }
3423
- gl.activeTexture(33984 + textureUnit);
3424
- gl.bindTexture(texture.glTarget, texture.handle);
3425
- textureUnit += 1;
3426
- break;
3427
- case "sampler":
3428
- break;
3429
- case "storage":
3430
- case "read-only-storage":
3431
- throw new Error(`binding type '${binding.type}' not supported in WebGL`);
3432
- }
3433
- }
3434
- }
3435
- /**
3436
- * Due to program sharing, uniforms need to be reset before every draw call
3437
- * (though caching will avoid redundant WebGL calls)
3438
- */
3439
- _applyUniforms(uniforms) {
3440
- for (const uniformLayout of this.shaderLayout.uniforms || []) {
3441
- const { name, location, type, textureUnit } = uniformLayout;
3442
- const value = uniforms[name] ?? textureUnit;
3443
- if (value !== void 0) {
3444
- setUniform(this.device.gl, location, type, value);
3445
- }
3446
- }
3447
- }
3448
- _syncLinkStatus() {
3449
- this.linkStatus = this.sharedRenderPipeline.linkStatus;
3450
- }
3451
- };
3452
- }
3453
- });
3454
-
3455
3216
  // ../../node_modules/@luma.gl/webgl/dist/adapter/converters/webgl-shadertypes.js
3456
3217
  function convertDataTypeToGLDataType(normalizedType) {
3457
3218
  return NORMALIZED_SHADER_TYPE_TO_WEBGL[normalizedType];
@@ -3534,13 +3295,13 @@ Source: ${sourceLine}` : "";
3534
3295
  });
3535
3296
 
3536
3297
  // ../../node_modules/@luma.gl/webgl/dist/adapter/helpers/get-shader-layout-from-glsl.js
3537
- function getShaderLayoutFromGLSL(gl, program) {
3298
+ function getShaderLayoutFromGLSL(gl, program, options = {}) {
3538
3299
  const shaderLayout = {
3539
3300
  attributes: [],
3540
3301
  bindings: []
3541
3302
  };
3542
3303
  shaderLayout.attributes = readAttributeDeclarations(gl, program);
3543
- const uniformBlocks = readUniformBlocks(gl, program);
3304
+ const uniformBlocks = readUniformBlocks(gl, program, options);
3544
3305
  for (const uniformBlock of uniformBlocks) {
3545
3306
  const uniforms2 = uniformBlock.uniforms.map((uniform) => ({
3546
3307
  name: uniform.name,
@@ -3554,7 +3315,7 @@ Source: ${sourceLine}` : "";
3554
3315
  name: uniformBlock.name,
3555
3316
  group: 0,
3556
3317
  location: uniformBlock.location,
3557
- visibility: (uniformBlock.vertex ? 1 : 0) & (uniformBlock.fragment ? 2 : 0),
3318
+ visibility: (uniformBlock.vertex ? 1 : 0) | (uniformBlock.fragment ? 2 : 0),
3558
3319
  minBindingSize: uniformBlock.byteLength,
3559
3320
  uniforms: uniforms2
3560
3321
  });
@@ -3624,7 +3385,7 @@ Source: ${sourceLine}` : "";
3624
3385
  }
3625
3386
  const { name, type: glUniformType, size } = activeInfo;
3626
3387
  const uniformType = convertGLUniformTypeToShaderVariableType(glUniformType);
3627
- const { type, components } = (0, import_core16.getVariableShaderTypeInfo)(uniformType);
3388
+ const { type, components } = (0, import_core15.getVariableShaderTypeInfo)(uniformType);
3628
3389
  varyings.push({ location, name, type, size: size * components });
3629
3390
  }
3630
3391
  varyings.sort((a, b) => a.location - b.location);
@@ -3661,84 +3422,530 @@ Source: ${sourceLine}` : "";
3661
3422
  };
3662
3423
  uniforms.push(arrayElementUniformInfo);
3663
3424
  }
3664
- }
3665
- }
3666
- return uniforms;
3667
- }
3668
- function readUniformBlocks(gl, program) {
3669
- const getBlockParameter = (blockIndex, pname) => gl.getActiveUniformBlockParameter(program, blockIndex, pname);
3670
- const uniformBlocks = [];
3671
- const blockCount = gl.getProgramParameter(program, 35382);
3672
- for (let blockIndex = 0; blockIndex < blockCount; blockIndex++) {
3673
- const blockInfo = {
3674
- name: gl.getActiveUniformBlockName(program, blockIndex) || "",
3675
- location: getBlockParameter(blockIndex, 35391),
3676
- byteLength: getBlockParameter(blockIndex, 35392),
3677
- vertex: getBlockParameter(blockIndex, 35396),
3678
- fragment: getBlockParameter(blockIndex, 35398),
3679
- uniformCount: getBlockParameter(blockIndex, 35394),
3680
- uniforms: []
3681
- };
3682
- const uniformIndices = getBlockParameter(blockIndex, 35395) || [];
3683
- const uniformType = gl.getActiveUniforms(program, uniformIndices, 35383);
3684
- const uniformArrayLength = gl.getActiveUniforms(program, uniformIndices, 35384);
3685
- const uniformOffset = gl.getActiveUniforms(program, uniformIndices, 35387);
3686
- const uniformStride = gl.getActiveUniforms(program, uniformIndices, 35388);
3687
- for (let i = 0; i < blockInfo.uniformCount; ++i) {
3688
- const uniformIndex = uniformIndices[i];
3689
- if (uniformIndex !== void 0) {
3690
- const activeInfo = gl.getActiveUniform(program, uniformIndex);
3691
- if (!activeInfo) {
3692
- throw new Error("activeInfo");
3693
- }
3694
- const format = convertGLUniformTypeToShaderVariableType(uniformType[i]);
3695
- blockInfo.uniforms.push({
3696
- name: activeInfo.name,
3697
- format,
3698
- type: uniformType[i],
3699
- arrayLength: uniformArrayLength[i],
3700
- byteOffset: uniformOffset[i],
3701
- byteStride: uniformStride[i]
3702
- // matrixStride: uniformStride[i],
3703
- // rowMajor: uniformRowMajor[i]
3425
+ }
3426
+ }
3427
+ return uniforms;
3428
+ }
3429
+ function readUniformBlocks(gl, program, options) {
3430
+ const uniformBlocks = [];
3431
+ const knownBlocksByIndex = getKnownUniformBlocksByIndex(gl, program, options);
3432
+ for (const [blockIndex, uniformBlock] of knownBlocksByIndex) {
3433
+ uniformBlocks.push(uniformBlock);
3434
+ try {
3435
+ const reflectedUniformBlock = readReflectedUniformBlock(gl, program, blockIndex, uniformBlock.name);
3436
+ validateReflectedUniformBlock(reflectedUniformBlock, uniformBlock);
3437
+ } catch (error) {
3438
+ const message2 = error instanceof Error ? error.message : String(error);
3439
+ import_core15.log.once(0, `WebGL uniform block reflection failed for "${uniformBlock.name}"; using supplied std140 metadata. ${message2}`)();
3440
+ }
3441
+ }
3442
+ const blockCount = gl.getProgramParameter(program, 35382);
3443
+ if (!Number.isInteger(blockCount) || blockCount < 0) {
3444
+ throw new Error(`Failed to reflect WebGL uniform blocks: ACTIVE_UNIFORM_BLOCKS returned ${String(blockCount)}`);
3445
+ }
3446
+ for (let blockIndex = 0; blockIndex < blockCount; blockIndex++) {
3447
+ if (!knownBlocksByIndex.has(blockIndex)) {
3448
+ uniformBlocks.push(readReflectedUniformBlock(gl, program, blockIndex));
3449
+ }
3450
+ }
3451
+ uniformBlocks.sort((a, b) => a.location - b.location);
3452
+ return uniformBlocks;
3453
+ }
3454
+ function validateReflectedUniformBlock(reflectedUniformBlock, knownUniformBlock) {
3455
+ for (const reflectedUniform of reflectedUniformBlock.uniforms) {
3456
+ const knownUniform = knownUniformBlock.uniforms.find((uniform) => reflectedUniform.name === uniform.name || reflectedUniform.name.endsWith(`.${uniform.name}`));
3457
+ if (!knownUniform) {
3458
+ throw new Error(`Failed to validate WebGL uniform block "${knownUniformBlock.name}": reflected unexpected member "${reflectedUniform.name}"`);
3459
+ }
3460
+ if (reflectedUniform.format !== knownUniform.format || reflectedUniform.arrayLength !== knownUniform.arrayLength || reflectedUniform.byteOffset !== knownUniform.byteOffset || reflectedUniform.byteStride !== knownUniform.byteStride) {
3461
+ throw new Error(`Failed to validate WebGL uniform block "${knownUniformBlock.name}": reflected layout for "${reflectedUniform.name}" does not match supplied std140 metadata`);
3462
+ }
3463
+ }
3464
+ }
3465
+ function getKnownUniformBlocksByIndex(gl, program, options) {
3466
+ const knownUniformBlocks = /* @__PURE__ */ new Map();
3467
+ for (const uniformBlockLayout of options.uniformBlockLayouts || []) {
3468
+ knownUniformBlocks.set(uniformBlockLayout.name, makeUniformBlockBindingFromTypes(uniformBlockLayout));
3469
+ }
3470
+ for (const binding of options.shaderLayout?.bindings || []) {
3471
+ if (isUsableUniformBlockBinding(binding)) {
3472
+ knownUniformBlocks.set(binding.name, binding);
3473
+ }
3474
+ }
3475
+ const knownBlocksByIndex = /* @__PURE__ */ new Map();
3476
+ for (const binding of knownUniformBlocks.values()) {
3477
+ const resolvedBlock = getActiveUniformBlockIndex(gl, program, binding.name);
3478
+ if (!resolvedBlock) {
3479
+ continue;
3480
+ }
3481
+ const { blockIndex, blockName } = resolvedBlock;
3482
+ if (knownBlocksByIndex.has(blockIndex)) {
3483
+ throw new Error(`Multiple supplied uniform block layouts resolve to active WebGL block "${blockName}"`);
3484
+ }
3485
+ knownBlocksByIndex.set(blockIndex, {
3486
+ name: blockName,
3487
+ location: blockIndex,
3488
+ byteLength: binding.minBindingSize,
3489
+ vertex: Boolean(binding.visibility && binding.visibility & 1),
3490
+ fragment: Boolean(binding.visibility && binding.visibility & 2),
3491
+ uniformCount: binding.uniforms.length,
3492
+ uniforms: binding.uniforms.map((uniform) => ({ ...uniform }))
3493
+ });
3494
+ }
3495
+ return knownBlocksByIndex;
3496
+ }
3497
+ function getActiveUniformBlockIndex(gl, program, blockName) {
3498
+ const blockNames = blockName.endsWith("Uniforms") ? [blockName, blockName.slice(0, -"Uniforms".length)] : [blockName, `${blockName}Uniforms`];
3499
+ for (const candidateBlockName of blockNames) {
3500
+ const blockIndex = gl.getUniformBlockIndex(program, candidateBlockName);
3501
+ if (blockIndex !== 4294967295) {
3502
+ if (!Number.isInteger(blockIndex) || blockIndex < 0) {
3503
+ throw new Error(`Failed to resolve WebGL uniform block "${candidateBlockName}": getUniformBlockIndex returned ${String(blockIndex)}`);
3504
+ }
3505
+ return { blockIndex, blockName: candidateBlockName };
3506
+ }
3507
+ }
3508
+ return null;
3509
+ }
3510
+ function readReflectedUniformBlock(gl, program, blockIndex, knownBlockName) {
3511
+ const blockName = knownBlockName || gl.getActiveUniformBlockName(program, blockIndex);
3512
+ if (!blockName) {
3513
+ throw new Error(`Failed to reflect WebGL uniform block at index ${blockIndex}: missing block name`);
3514
+ }
3515
+ const getBlockParameter = (pname, label) => {
3516
+ const value = gl.getActiveUniformBlockParameter(program, blockIndex, pname);
3517
+ if (value === null || value === void 0) {
3518
+ throw new Error(`Failed to reflect WebGL uniform block "${blockName}": ${label} returned null`);
3519
+ }
3520
+ return value;
3521
+ };
3522
+ const location = getFiniteInteger(getBlockParameter(35391, "UNIFORM_BLOCK_BINDING"), blockName, "UNIFORM_BLOCK_BINDING", 0);
3523
+ const byteLength = getFiniteInteger(getBlockParameter(35392, "UNIFORM_BLOCK_DATA_SIZE"), blockName, "UNIFORM_BLOCK_DATA_SIZE", 0);
3524
+ const uniformCount = getFiniteInteger(getBlockParameter(35394, "UNIFORM_BLOCK_ACTIVE_UNIFORMS"), blockName, "UNIFORM_BLOCK_ACTIVE_UNIFORMS", 0);
3525
+ const uniformIndices = getNumericArray(getBlockParameter(35395, "UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES"), blockName, "UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES", uniformCount);
3526
+ const uniformTypes = getActiveUniformValues(gl, program, uniformIndices, 35383, "UNIFORM_TYPE", blockName, uniformCount);
3527
+ const uniformArrayLengths = getActiveUniformValues(gl, program, uniformIndices, 35384, "UNIFORM_SIZE", blockName, uniformCount);
3528
+ const uniformBlockIndices = getActiveUniformValues(gl, program, uniformIndices, 35386, "UNIFORM_BLOCK_INDEX", blockName, uniformCount);
3529
+ const uniformOffsets = getActiveUniformValues(gl, program, uniformIndices, 35387, "UNIFORM_OFFSET", blockName, uniformCount);
3530
+ const uniformStrides = getActiveUniformValues(gl, program, uniformIndices, 35388, "UNIFORM_ARRAY_STRIDE", blockName, uniformCount);
3531
+ const uniforms = [];
3532
+ for (let uniformPosition = 0; uniformPosition < uniformCount; uniformPosition++) {
3533
+ if (uniformBlockIndices[uniformPosition] !== blockIndex) {
3534
+ throw new Error(`Failed to reflect WebGL uniform block "${blockName}": active uniform index ${uniformIndices[uniformPosition]} belongs to block ${uniformBlockIndices[uniformPosition]}, expected ${blockIndex}`);
3535
+ }
3536
+ const uniformIndex = uniformIndices[uniformPosition];
3537
+ const activeInfo = gl.getActiveUniform(program, uniformIndex);
3538
+ if (!activeInfo) {
3539
+ throw new Error(`Failed to reflect WebGL uniform block "${blockName}": getActiveUniform(${uniformIndex}) returned null`);
3540
+ }
3541
+ const uniformType = getFiniteInteger(uniformTypes[uniformPosition], blockName, `UNIFORM_TYPE[${uniformPosition}]`, 1);
3542
+ const arrayLength = getFiniteInteger(uniformArrayLengths[uniformPosition], blockName, `UNIFORM_SIZE[${uniformPosition}]`, 1);
3543
+ const byteOffset = getFiniteInteger(uniformOffsets[uniformPosition], blockName, `UNIFORM_OFFSET[${uniformPosition}]`, 0);
3544
+ const byteStride = getFiniteInteger(uniformStrides[uniformPosition], blockName, `UNIFORM_ARRAY_STRIDE[${uniformPosition}]`, 0);
3545
+ if (activeInfo.type !== uniformType || activeInfo.size !== arrayLength) {
3546
+ throw new Error(`Failed to reflect WebGL uniform block "${blockName}": getActiveUniform(${uniformIndex}) disagrees with getActiveUniforms`);
3547
+ }
3548
+ uniforms.push({
3549
+ name: activeInfo.name,
3550
+ format: convertGLUniformTypeToShaderVariableType(uniformType),
3551
+ arrayLength,
3552
+ byteOffset,
3553
+ byteStride
3554
+ });
3555
+ }
3556
+ const blockInfo = {
3557
+ name: blockName,
3558
+ location,
3559
+ byteLength,
3560
+ vertex: Boolean(getBlockParameter(35396, "UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER")),
3561
+ fragment: Boolean(getBlockParameter(35398, "UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER")),
3562
+ uniformCount,
3563
+ uniforms
3564
+ };
3565
+ const uniformInstancePrefixes = new Set(blockInfo.uniforms.map((uniform) => uniform.name.split(".")[0]).filter((instanceName) => Boolean(instanceName)));
3566
+ const blockAlias = blockInfo.name.replace(/Uniforms$/, "");
3567
+ if (uniformInstancePrefixes.size === 1 && !uniformInstancePrefixes.has(blockInfo.name) && !uniformInstancePrefixes.has(blockAlias)) {
3568
+ const [instanceName] = uniformInstancePrefixes;
3569
+ import_core15.log.warn(`Uniform block "${blockInfo.name}" uses GLSL instance "${instanceName}". luma.gl binds uniform buffers by block name ("${blockInfo.name}") and alias ("${blockAlias}"). Prefer matching the instance name to one of those to avoid confusing silent mismatches.`)();
3570
+ }
3571
+ return blockInfo;
3572
+ }
3573
+ function getActiveUniformValues(gl, program, uniformIndices, pname, label, blockName, expectedLength) {
3574
+ const values = gl.getActiveUniforms(program, uniformIndices, pname);
3575
+ if (values === null) {
3576
+ throw new Error(`Failed to reflect WebGL uniform block "${blockName}": ${label} returned null`);
3577
+ }
3578
+ return getNumericArray(values, blockName, label, expectedLength);
3579
+ }
3580
+ function getNumericArray(value, blockName, label, expectedLength) {
3581
+ if (!Array.isArray(value) && !ArrayBuffer.isView(value)) {
3582
+ throw new Error(`Failed to reflect WebGL uniform block "${blockName}": ${label} returned a non-array value`);
3583
+ }
3584
+ const values = Array.from(value);
3585
+ if (values.length !== expectedLength || values.some((item) => !Number.isInteger(item))) {
3586
+ throw new Error(`Failed to reflect WebGL uniform block "${blockName}": ${label} returned ${values.length} invalid values, expected ${expectedLength}`);
3587
+ }
3588
+ return values;
3589
+ }
3590
+ function getFiniteInteger(value, blockName, label, minimum) {
3591
+ if (!Number.isInteger(value) || value < minimum) {
3592
+ throw new Error(`Failed to reflect WebGL uniform block "${blockName}": ${label} returned ${String(value)}`);
3593
+ }
3594
+ return value;
3595
+ }
3596
+ function makeUniformBlockBindingFromTypes(uniformBlockLayout) {
3597
+ const shaderBlockLayout = (0, import_core15.makeShaderBlockLayout)(uniformBlockLayout.uniformTypes, {
3598
+ layout: "std140"
3599
+ });
3600
+ const uniforms = getUniformInfosFromTypes(uniformBlockLayout.uniformTypes, shaderBlockLayout.fields);
3601
+ return {
3602
+ type: "uniform",
3603
+ name: uniformBlockLayout.name,
3604
+ group: 0,
3605
+ location: 0,
3606
+ minBindingSize: shaderBlockLayout.byteLength,
3607
+ uniforms
3608
+ };
3609
+ }
3610
+ function getUniformInfosFromTypes(uniformTypes, fields) {
3611
+ const uniforms = [];
3612
+ const addType = (name, type) => {
3613
+ if (typeof type === "string") {
3614
+ const field = fields[name];
3615
+ if (!field) {
3616
+ throw new Error(`Missing std140 layout field ${name}`);
3617
+ }
3618
+ uniforms.push({
3619
+ name,
3620
+ format: field.shaderType,
3621
+ arrayLength: 1,
3622
+ byteOffset: field.offset * 4,
3623
+ byteStride: 0
3624
+ });
3625
+ return;
3626
+ }
3627
+ if (Array.isArray(type)) {
3628
+ addArrayType(name, type[0], type[1]);
3629
+ return;
3630
+ }
3631
+ for (const [memberName, memberType] of Object.entries(type)) {
3632
+ addType(`${name}.${memberName}`, memberType);
3633
+ }
3634
+ };
3635
+ const addArrayType = (name, type, arrayLength) => {
3636
+ if (typeof type === "string") {
3637
+ const firstField = fields[`${name}[0]`];
3638
+ const secondField = arrayLength > 1 ? fields[`${name}[1]`] : void 0;
3639
+ if (!firstField) {
3640
+ throw new Error(`Missing std140 array layout field ${name}[0]`);
3641
+ }
3642
+ uniforms.push({
3643
+ name: `${name}[0]`,
3644
+ format: firstField.shaderType,
3645
+ arrayLength,
3646
+ byteOffset: firstField.offset * 4,
3647
+ byteStride: secondField ? (secondField.offset - firstField.offset) * 4 : 0
3648
+ });
3649
+ return;
3650
+ }
3651
+ if (Array.isArray(type)) {
3652
+ throw new Error(`Nested uniform arrays are not supported for ${name}`);
3653
+ }
3654
+ for (const [memberName, memberType] of Object.entries(type)) {
3655
+ if (typeof memberType !== "string") {
3656
+ throw new Error(`Composite uniform array members are not supported for ${name}`);
3657
+ }
3658
+ const firstName = `${name}[0].${memberName}`;
3659
+ const secondName = `${name}[1].${memberName}`;
3660
+ const firstField = fields[firstName];
3661
+ const secondField = arrayLength > 1 ? fields[secondName] : void 0;
3662
+ if (!firstField) {
3663
+ throw new Error(`Missing std140 array layout field ${firstName}`);
3664
+ }
3665
+ uniforms.push({
3666
+ name: firstName,
3667
+ format: firstField.shaderType,
3668
+ arrayLength,
3669
+ byteOffset: firstField.offset * 4,
3670
+ byteStride: secondField ? (secondField.offset - firstField.offset) * 4 : 0
3671
+ });
3672
+ }
3673
+ };
3674
+ for (const [uniformName, uniformType] of Object.entries(uniformTypes)) {
3675
+ addType(uniformName, uniformType);
3676
+ }
3677
+ return uniforms;
3678
+ }
3679
+ function isUsableUniformBlockBinding(binding) {
3680
+ return binding.type === "uniform" && Number.isInteger(binding.minBindingSize) && binding.minBindingSize >= 0 && Array.isArray(binding.uniforms) && binding.uniforms.every((uniform) => typeof uniform.name === "string" && typeof uniform.format === "string" && Number.isInteger(uniform.arrayLength) && uniform.arrayLength > 0 && Number.isInteger(uniform.byteOffset) && uniform.byteOffset >= 0 && Number.isInteger(uniform.byteStride) && uniform.byteStride >= 0);
3681
+ }
3682
+ function parseUniformName(name) {
3683
+ if (name[name.length - 1] !== "]") {
3684
+ return {
3685
+ name,
3686
+ length: 1,
3687
+ isArray: false
3688
+ };
3689
+ }
3690
+ const UNIFORM_NAME_REGEXP = /([^[]*)(\[[0-9]+\])?/;
3691
+ const matches = UNIFORM_NAME_REGEXP.exec(name);
3692
+ const uniformName = (0, import_core15.assertDefined)(matches?.[1], `Failed to parse GLSL uniform name ${name}`);
3693
+ return {
3694
+ name: uniformName,
3695
+ // TODO - is this a bug, shouldn't we return the value?
3696
+ length: matches?.[2] ? 1 : 0,
3697
+ isArray: Boolean(matches?.[2])
3698
+ };
3699
+ }
3700
+ var import_core15;
3701
+ var init_get_shader_layout_from_glsl = __esm({
3702
+ "../../node_modules/@luma.gl/webgl/dist/adapter/helpers/get-shader-layout-from-glsl.js"() {
3703
+ import_core15 = __toESM(require_core2(), 1);
3704
+ init_webgl_shadertypes();
3705
+ }
3706
+ });
3707
+
3708
+ // ../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-render-pipeline.js
3709
+ function mergeShaderLayout(baseLayout, overrideLayout) {
3710
+ const mergedLayout = {
3711
+ ...baseLayout,
3712
+ attributes: baseLayout.attributes.map((attribute) => ({ ...attribute })),
3713
+ bindings: baseLayout.bindings.map((binding) => ({ ...binding }))
3714
+ };
3715
+ for (const attribute of overrideLayout?.attributes || []) {
3716
+ const baseAttribute = mergedLayout.attributes.find((attr) => attr.name === attribute.name);
3717
+ if (!baseAttribute) {
3718
+ import_core16.log.warn(`shader layout attribute ${attribute.name} not present in shader`);
3719
+ } else {
3720
+ baseAttribute.type = attribute.type || baseAttribute.type;
3721
+ baseAttribute.stepMode = attribute.stepMode || baseAttribute.stepMode;
3722
+ }
3723
+ }
3724
+ for (const binding of overrideLayout?.bindings || []) {
3725
+ const baseBinding = getShaderLayoutBindingByName(mergedLayout, binding.name);
3726
+ if (!baseBinding) {
3727
+ import_core16.log.warn(`shader layout binding ${binding.name} not present in shader`);
3728
+ continue;
3729
+ }
3730
+ Object.assign(baseBinding, binding);
3731
+ }
3732
+ return mergedLayout;
3733
+ }
3734
+ function getShaderLayoutBindingByName(shaderLayout, bindingName) {
3735
+ return shaderLayout.bindings.find((binding) => binding.name === bindingName || binding.name === `${bindingName}Uniforms` || `${binding.name}Uniforms` === bindingName);
3736
+ }
3737
+ function getBindingValueForLayoutBinding(bindings, bindingName) {
3738
+ return bindings[bindingName] || bindings[`${bindingName}Uniforms`] || bindings[bindingName.replace(/Uniforms$/, "")];
3739
+ }
3740
+ var import_core16, WEBGLRenderPipeline;
3741
+ var init_webgl_render_pipeline = __esm({
3742
+ "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-render-pipeline.js"() {
3743
+ import_core16 = __toESM(require_core2(), 1);
3744
+ init_set_uniform();
3745
+ init_webgl_buffer();
3746
+ init_webgl_framebuffer();
3747
+ init_webgl_texture();
3748
+ init_webgl_texture_view();
3749
+ init_get_shader_layout_from_glsl();
3750
+ WEBGLRenderPipeline = class extends import_core16.RenderPipeline {
3751
+ /** The WebGL device that created this render pipeline */
3752
+ device;
3753
+ /** Handle to underlying WebGL program */
3754
+ handle;
3755
+ /** vertex shader */
3756
+ vs;
3757
+ /** fragment shader */
3758
+ fs;
3759
+ /** The layout extracted from shader by WebGL introspection APIs */
3760
+ introspectedLayout;
3761
+ /** Compatibility path for direct pipeline.setBindings() usage */
3762
+ bindings = {};
3763
+ /** Compatibility path for direct pipeline.uniforms usage */
3764
+ uniforms = {};
3765
+ /** WebGL varyings */
3766
+ varyings = null;
3767
+ _uniformCount = 0;
3768
+ _uniformSetters = {};
3769
+ // TODO are these used?
3770
+ get [Symbol.toStringTag]() {
3771
+ return "WEBGLRenderPipeline";
3772
+ }
3773
+ constructor(device, props) {
3774
+ super(device, props);
3775
+ this.device = device;
3776
+ const webglSharedRenderPipeline = this.sharedRenderPipeline || this.device._createSharedRenderPipelineWebGL(props);
3777
+ this.sharedRenderPipeline = webglSharedRenderPipeline;
3778
+ this.handle = webglSharedRenderPipeline.handle;
3779
+ this.vs = webglSharedRenderPipeline.vs;
3780
+ this.fs = webglSharedRenderPipeline.fs;
3781
+ this.linkStatus = webglSharedRenderPipeline.linkStatus;
3782
+ this.introspectedLayout = getShaderLayoutFromGLSL(this.device.gl, this.handle, {
3783
+ uniformBlockLayouts: props._uniformBlockLayouts,
3784
+ shaderLayout: props.shaderLayout
3785
+ });
3786
+ this.device._setWebGLDebugMetadata(this.handle, this, { spector: { id: this.props.id } });
3787
+ this.shaderLayout = props.shaderLayout ? mergeShaderLayout(this.introspectedLayout, props.shaderLayout) : this.introspectedLayout;
3788
+ }
3789
+ destroy() {
3790
+ if (this.destroyed) {
3791
+ return;
3792
+ }
3793
+ if (this.sharedRenderPipeline && !this.props._sharedRenderPipeline) {
3794
+ this.sharedRenderPipeline.destroy();
3795
+ }
3796
+ this.destroyResource();
3797
+ }
3798
+ /** @deprecated Set bindings on RenderPass instead. Will be removed in the next major release. */
3799
+ setBindings(bindings, options) {
3800
+ const flatBindings = (0, import_core16.flattenBindingsByGroup)((0, import_core16.normalizeBindingsByGroup)(this.shaderLayout, bindings));
3801
+ for (const [name, value] of Object.entries(flatBindings)) {
3802
+ const binding = getShaderLayoutBindingByName(this.shaderLayout, name);
3803
+ if (!binding) {
3804
+ const validBindings = this.shaderLayout.bindings.map((binding_) => `"${binding_.name}"`).join(", ");
3805
+ if (!options?.disableWarnings) {
3806
+ import_core16.log.warn(`No binding "${name}" in render pipeline "${this.id}", expected one of ${validBindings}`, value)();
3807
+ }
3808
+ } else {
3809
+ if (!value) {
3810
+ import_core16.log.warn(`Unsetting binding "${name}" in render pipeline "${this.id}"`)();
3811
+ }
3812
+ switch (binding.type) {
3813
+ case "uniform":
3814
+ if (!(value instanceof WEBGLBuffer) && !(value.buffer instanceof WEBGLBuffer)) {
3815
+ throw new Error("buffer value");
3816
+ }
3817
+ break;
3818
+ case "texture":
3819
+ if (!(value instanceof WEBGLTextureView || value instanceof WEBGLTexture || value instanceof WEBGLFramebuffer)) {
3820
+ throw new Error(`${this} Bad texture binding for ${name}`);
3821
+ }
3822
+ break;
3823
+ case "sampler":
3824
+ import_core16.log.warn(`Ignoring sampler ${name}`)();
3825
+ break;
3826
+ default:
3827
+ throw new Error(binding.type);
3828
+ }
3829
+ this.bindings[name] = value;
3830
+ }
3831
+ }
3832
+ }
3833
+ /** @todo needed for portable model
3834
+ * @note The WebGL API is offers many ways to draw things
3835
+ * This function unifies those ways into a single call using common parameters with sane defaults
3836
+ */
3837
+ draw(options) {
3838
+ const webglRenderPass = options.renderPass;
3839
+ const drawBindings = options.bindGroups ? (0, import_core16.flattenBindingsByGroup)(options.bindGroups) : options.bindings || this.bindings;
3840
+ webglRenderPass.setPipeline(this);
3841
+ webglRenderPass.setBindings(drawBindings);
3842
+ webglRenderPass.setVertexArray(options.vertexArray);
3843
+ return webglRenderPass.draw({
3844
+ parameters: options.parameters,
3845
+ topology: options.topology,
3846
+ isInstanced: options.isInstanced,
3847
+ vertexCount: options.vertexCount,
3848
+ indexCount: options.indexCount,
3849
+ instanceCount: options.instanceCount,
3850
+ firstVertex: options.firstVertex,
3851
+ firstIndex: options.firstIndex,
3852
+ firstInstance: options.firstInstance,
3853
+ baseVertex: options.baseVertex,
3854
+ transformFeedback: options.transformFeedback,
3855
+ uniforms: options.uniforms
3704
3856
  });
3705
3857
  }
3706
- }
3707
- const uniformInstancePrefixes = new Set(blockInfo.uniforms.map((uniform) => uniform.name.split(".")[0]).filter((instanceName) => Boolean(instanceName)));
3708
- const blockAlias = blockInfo.name.replace(/Uniforms$/, "");
3709
- if (uniformInstancePrefixes.size === 1 && !uniformInstancePrefixes.has(blockInfo.name) && !uniformInstancePrefixes.has(blockAlias)) {
3710
- const [instanceName] = uniformInstancePrefixes;
3711
- import_core16.log.warn(`Uniform block "${blockInfo.name}" uses GLSL instance "${instanceName}". luma.gl binds uniform buffers by block name ("${blockInfo.name}") and alias ("${blockAlias}"). Prefer matching the instance name to one of those to avoid confusing silent mismatches.`)();
3712
- }
3713
- uniformBlocks.push(blockInfo);
3714
- }
3715
- uniformBlocks.sort((a, b) => a.location - b.location);
3716
- return uniformBlocks;
3717
- }
3718
- function parseUniformName(name) {
3719
- if (name[name.length - 1] !== "]") {
3720
- return {
3721
- name,
3722
- length: 1,
3723
- isArray: false
3858
+ /**
3859
+ * Checks if all texture-values uniforms are renderable (i.e. loaded)
3860
+ * Update a texture if needed (e.g. from video)
3861
+ * Note: This is currently done before every draw call
3862
+ */
3863
+ _areTexturesRenderable(bindings) {
3864
+ let texturesRenderable = true;
3865
+ for (const bindingInfo of this.shaderLayout.bindings) {
3866
+ if (!getBindingValueForLayoutBinding(bindings, bindingInfo.name)) {
3867
+ import_core16.log.warn(`Binding ${bindingInfo.name} not found in ${this.id}`)();
3868
+ texturesRenderable = false;
3869
+ }
3870
+ }
3871
+ return texturesRenderable;
3872
+ }
3873
+ /** Apply any bindings (before each draw call) */
3874
+ _applyBindings(bindings, _options) {
3875
+ this._syncLinkStatus();
3876
+ if (this.linkStatus !== "success") {
3877
+ return;
3878
+ }
3879
+ const { gl } = this.device;
3880
+ gl.useProgram(this.handle);
3881
+ let textureUnit = 0;
3882
+ let uniformBufferIndex = 0;
3883
+ for (const binding of this.shaderLayout.bindings) {
3884
+ const value = getBindingValueForLayoutBinding(bindings, binding.name);
3885
+ if (!value) {
3886
+ throw new Error(`No value for binding ${binding.name} in ${this.id}`);
3887
+ }
3888
+ switch (binding.type) {
3889
+ case "uniform":
3890
+ const { name } = binding;
3891
+ const location = gl.getUniformBlockIndex(this.handle, name);
3892
+ if (location === 4294967295) {
3893
+ throw new Error(`Invalid uniform block name ${name}`);
3894
+ }
3895
+ gl.uniformBlockBinding(this.handle, location, uniformBufferIndex);
3896
+ if (value instanceof WEBGLBuffer) {
3897
+ gl.bindBufferBase(35345, uniformBufferIndex, value.handle);
3898
+ } else {
3899
+ const bufferBinding = value;
3900
+ gl.bindBufferRange(35345, uniformBufferIndex, bufferBinding.buffer.handle, bufferBinding.offset || 0, bufferBinding.size || bufferBinding.buffer.byteLength - (bufferBinding.offset || 0));
3901
+ }
3902
+ uniformBufferIndex += 1;
3903
+ break;
3904
+ case "texture":
3905
+ if (!(value instanceof WEBGLTextureView || value instanceof WEBGLTexture || value instanceof WEBGLFramebuffer)) {
3906
+ throw new Error("texture");
3907
+ }
3908
+ let texture;
3909
+ if (value instanceof WEBGLTextureView) {
3910
+ texture = value.texture;
3911
+ } else if (value instanceof WEBGLTexture) {
3912
+ texture = value;
3913
+ } else if (value instanceof WEBGLFramebuffer && value.colorAttachments[0] instanceof WEBGLTextureView) {
3914
+ import_core16.log.warn("Passing framebuffer in texture binding may be deprecated. Use fbo.colorAttachments[0] instead")();
3915
+ texture = value.colorAttachments[0].texture;
3916
+ } else {
3917
+ throw new Error("No texture");
3918
+ }
3919
+ gl.activeTexture(33984 + textureUnit);
3920
+ gl.bindTexture(texture.glTarget, texture.handle);
3921
+ textureUnit += 1;
3922
+ break;
3923
+ case "sampler":
3924
+ break;
3925
+ case "storage":
3926
+ case "read-only-storage":
3927
+ throw new Error(`binding type '${binding.type}' not supported in WebGL`);
3928
+ }
3929
+ }
3930
+ }
3931
+ /**
3932
+ * Due to program sharing, uniforms need to be reset before every draw call
3933
+ * (though caching will avoid redundant WebGL calls)
3934
+ */
3935
+ _applyUniforms(uniforms) {
3936
+ for (const uniformLayout of this.shaderLayout.uniforms || []) {
3937
+ const { name, location, type, textureUnit } = uniformLayout;
3938
+ const value = uniforms[name] ?? textureUnit;
3939
+ if (value !== void 0) {
3940
+ setUniform(this.device.gl, location, type, value);
3941
+ }
3942
+ }
3943
+ }
3944
+ _syncLinkStatus() {
3945
+ this.linkStatus = this.sharedRenderPipeline.linkStatus;
3946
+ }
3724
3947
  };
3725
3948
  }
3726
- const UNIFORM_NAME_REGEXP = /([^[]*)(\[[0-9]+\])?/;
3727
- const matches = UNIFORM_NAME_REGEXP.exec(name);
3728
- const uniformName = (0, import_core16.assertDefined)(matches?.[1], `Failed to parse GLSL uniform name ${name}`);
3729
- return {
3730
- name: uniformName,
3731
- // TODO - is this a bug, shouldn't we return the value?
3732
- length: matches?.[2] ? 1 : 0,
3733
- isArray: Boolean(matches?.[2])
3734
- };
3735
- }
3736
- var import_core16;
3737
- var init_get_shader_layout_from_glsl = __esm({
3738
- "../../node_modules/@luma.gl/webgl/dist/adapter/helpers/get-shader-layout-from-glsl.js"() {
3739
- import_core16 = __toESM(require_core2(), 1);
3740
- init_webgl_shadertypes();
3741
- }
3742
3949
  });
3743
3950
 
3744
3951
  // ../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-shared-render-pipeline.js
@@ -3746,7 +3953,6 @@ Source: ${sourceLine}` : "";
3746
3953
  var init_webgl_shared_render_pipeline = __esm({
3747
3954
  "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-shared-render-pipeline.js"() {
3748
3955
  import_core17 = __toESM(require_core2(), 1);
3749
- init_get_shader_layout_from_glsl();
3750
3956
  init_webgl_shadertypes();
3751
3957
  LOG_PROGRAM_PERF_PRIORITY = 4;
3752
3958
  WEBGLSharedRenderPipeline = class extends import_core17.SharedRenderPipeline {
@@ -3754,7 +3960,6 @@ Source: ${sourceLine}` : "";
3754
3960
  handle;
3755
3961
  vs;
3756
3962
  fs;
3757
- introspectedLayout = { attributes: [], bindings: [], uniforms: [] };
3758
3963
  linkStatus = "pending";
3759
3964
  constructor(device, props) {
3760
3965
  super(device, props);
@@ -3766,9 +3971,6 @@ Source: ${sourceLine}` : "";
3766
3971
  this.device.gl.transformFeedbackVaryings(this.handle, props.varyings, props.bufferMode || 35981);
3767
3972
  }
3768
3973
  this._linkShaders();
3769
- import_core17.log.time(3, `RenderPipeline ${this.id} - shaderLayout introspection`)();
3770
- this.introspectedLayout = getShaderLayoutFromGLSL(this.device.gl, this.handle);
3771
- import_core17.log.timeEnd(3, `RenderPipeline ${this.id} - shaderLayout introspection`)();
3772
3974
  }
3773
3975
  destroy() {
3774
3976
  if (this.destroyed) {
@@ -11463,8 +11665,8 @@ void main(void) {
11463
11665
  }
11464
11666
  return PROJECTION_MODE.IDENTITY;
11465
11667
  }
11466
- // Two viewports are equal if width and height are identical, and if
11467
- // their view and projection matrices are (approximately) equal.
11668
+ // Two viewports are equal if their dimensions, common-space scale, and
11669
+ // view and projection matrices are (approximately) equal.
11468
11670
  equals(viewport) {
11469
11671
  if (!(viewport instanceof _Viewport)) {
11470
11672
  return false;
@@ -11472,7 +11674,7 @@ void main(void) {
11472
11674
  if (this === viewport) {
11473
11675
  return true;
11474
11676
  }
11475
- return viewport.width === this.width && viewport.height === this.height && viewport.scale === this.scale && equals(viewport.projectionMatrix, this.projectionMatrix) && equals(viewport.viewMatrix, this.viewMatrix);
11677
+ return viewport.width === this.width && viewport.height === this.height && viewport.scale === this.scale && viewport.projectionMode === this.projectionMode && viewport.resolution === this.resolution && equals(viewport.distanceScales.unitsPerMeter, this.distanceScales.unitsPerMeter) && equals(viewport.projectionMatrix, this.projectionMatrix) && equals(viewport.viewMatrix, this.viewMatrix);
11476
11678
  }
11477
11679
  /**
11478
11680
  * Projects xyz (possibly latitude and longitude) to pixel coordinates in window
@@ -11807,6 +12009,10 @@ void main(void) {
11807
12009
  }
11808
12010
  return this._subViewports;
11809
12011
  }
12012
+ /** Returns whether two Web Mercator viewports use the same projection settings. */
12013
+ equals(viewport) {
12014
+ return viewport instanceof _WebMercatorViewport && viewport._pseudoMeters === this._pseudoMeters && super.equals(viewport);
12015
+ }
11810
12016
  projectPosition(xyz) {
11811
12017
  if (this._pseudoMeters) {
11812
12018
  return super.projectPosition(xyz);
@@ -12177,178 +12383,6 @@ void main(void) {
12177
12383
  }
12178
12384
  };
12179
12385
 
12180
- // ../core/src/viewports/globe-viewport.ts
12181
- var DEGREES_TO_RADIANS5 = Math.PI / 180;
12182
- var RADIANS_TO_DEGREES3 = 180 / Math.PI;
12183
- var EARTH_RADIUS = 6370972;
12184
- var GLOBE_RADIUS = 256;
12185
- function getDistanceScales2() {
12186
- const unitsPerMeter2 = GLOBE_RADIUS / EARTH_RADIUS;
12187
- const unitsPerDegree = Math.PI / 180 * GLOBE_RADIUS;
12188
- return {
12189
- unitsPerMeter: [unitsPerMeter2, unitsPerMeter2, unitsPerMeter2],
12190
- unitsPerMeter2: [0, 0, 0],
12191
- metersPerUnit: [1 / unitsPerMeter2, 1 / unitsPerMeter2, 1 / unitsPerMeter2],
12192
- unitsPerDegree: [unitsPerDegree, unitsPerDegree, unitsPerMeter2],
12193
- unitsPerDegree2: [0, 0, 0],
12194
- degreesPerUnit: [1 / unitsPerDegree, 1 / unitsPerDegree, 1 / unitsPerMeter2]
12195
- };
12196
- }
12197
- var GlobeViewport = class extends Viewport {
12198
- constructor(opts = {}) {
12199
- const {
12200
- longitude = 0,
12201
- bearing = 0,
12202
- pitch = 0,
12203
- zoom = 0,
12204
- // Matches Maplibre defaults
12205
- // https://github.com/maplibre/maplibre-gl-js/blob/f8ab4b48d59ab8fe7b068b102538793bbdd4c848/src/geo/projection/globe_transform.ts#L632-L633
12206
- nearZMultiplier = 0.5,
12207
- farZMultiplier = 1,
12208
- resolution = 10
12209
- } = opts;
12210
- let { latitude = 0, height, altitude = 1.5, fovy } = opts;
12211
- latitude = Math.max(Math.min(latitude, 90), -90);
12212
- height = height || 1;
12213
- if (fovy) {
12214
- altitude = fovyToAltitude(fovy);
12215
- } else {
12216
- fovy = altitudeToFovy(altitude);
12217
- }
12218
- const scaleLatitude = Math.max(Math.min(latitude, MAX_LATITUDE), -MAX_LATITUDE);
12219
- const scale5 = Math.pow(2, zoom - zoomAdjust(scaleLatitude));
12220
- const pitchRadians = pitch * DEGREES_TO_RADIANS5;
12221
- const nearZ = opts.nearZ ?? nearZMultiplier;
12222
- const farZ = opts.farZ ?? (altitude + GLOBE_RADIUS * 2 * scale5 / height / Math.max(Math.cos(pitchRadians), 0.1)) * farZMultiplier;
12223
- const viewMatrix = new Matrix4().lookAt({ eye: [0, -altitude, 0], up: [0, 0, 1] }).rotateX(-pitchRadians).rotateY(-bearing * DEGREES_TO_RADIANS5).rotateX(latitude * DEGREES_TO_RADIANS5).rotateZ(-longitude * DEGREES_TO_RADIANS5).scale(scale5 / height);
12224
- super({
12225
- ...opts,
12226
- // x, y, width,
12227
- height,
12228
- // view matrix
12229
- viewMatrix,
12230
- longitude,
12231
- latitude,
12232
- zoom,
12233
- // projection matrix parameters
12234
- distanceScales: getDistanceScales2(),
12235
- fovy,
12236
- focalDistance: altitude,
12237
- near: nearZ,
12238
- far: farZ
12239
- });
12240
- this.scale = scale5;
12241
- this.latitude = latitude;
12242
- this.longitude = longitude;
12243
- this.bearing = bearing;
12244
- this.pitch = pitch;
12245
- this.fovy = fovy;
12246
- this.resolution = resolution;
12247
- }
12248
- get projectionMode() {
12249
- return PROJECTION_MODE.GLOBE;
12250
- }
12251
- getDistanceScales() {
12252
- return this.distanceScales;
12253
- }
12254
- getBounds(options = {}) {
12255
- const unprojectOption = { targetZ: options.z || 0 };
12256
- const left = this.unproject([0, this.height / 2], unprojectOption);
12257
- const top = this.unproject([this.width / 2, 0], unprojectOption);
12258
- const right = this.unproject([this.width, this.height / 2], unprojectOption);
12259
- const bottom = this.unproject([this.width / 2, this.height], unprojectOption);
12260
- if (right[0] < this.longitude) right[0] += 360;
12261
- if (left[0] > this.longitude) left[0] -= 360;
12262
- return [
12263
- Math.min(left[0], right[0], top[0], bottom[0]),
12264
- Math.min(left[1], right[1], top[1], bottom[1]),
12265
- Math.max(left[0], right[0], top[0], bottom[0]),
12266
- Math.max(left[1], right[1], top[1], bottom[1])
12267
- ];
12268
- }
12269
- unproject(xyz, { topLeft = true, targetZ } = {}) {
12270
- const [x, y, z] = xyz;
12271
- const y2 = topLeft ? y : this.height - y;
12272
- const { pixelUnprojectionMatrix } = this;
12273
- let coord;
12274
- if (Number.isFinite(z)) {
12275
- coord = transformVector2(pixelUnprojectionMatrix, [x, y2, z, 1]);
12276
- } else {
12277
- const coord0 = transformVector2(pixelUnprojectionMatrix, [x, y2, -1, 1]);
12278
- const coord1 = transformVector2(pixelUnprojectionMatrix, [x, y2, 1, 1]);
12279
- const lt = ((targetZ || 0) / EARTH_RADIUS + 1) * GLOBE_RADIUS;
12280
- const lSqr = vec3_exports.sqrLen(vec3_exports.sub([], coord0, coord1));
12281
- const l0Sqr = vec3_exports.sqrLen(coord0);
12282
- const l1Sqr = vec3_exports.sqrLen(coord1);
12283
- const sSqr = (4 * l0Sqr * l1Sqr - (lSqr - l0Sqr - l1Sqr) ** 2) / 16;
12284
- const dSqr = 4 * sSqr / lSqr;
12285
- const r0 = Math.sqrt(l0Sqr - dSqr);
12286
- const dr = Math.sqrt(Math.max(0, lt * lt - dSqr));
12287
- const t = (r0 - dr) / Math.sqrt(lSqr);
12288
- coord = vec3_exports.lerp([], coord0, coord1, t);
12289
- }
12290
- const [X, Y, Z] = this.unprojectPosition(coord);
12291
- if (Number.isFinite(z)) {
12292
- return [X, Y, Z];
12293
- }
12294
- return Number.isFinite(targetZ) ? [X, Y, targetZ] : [X, Y];
12295
- }
12296
- projectPosition(xyz) {
12297
- const [lng, lat, Z = 0] = xyz;
12298
- const lambda = lng * DEGREES_TO_RADIANS5;
12299
- const phi = lat * DEGREES_TO_RADIANS5;
12300
- const cosPhi = Math.cos(phi);
12301
- const D = (Z / EARTH_RADIUS + 1) * GLOBE_RADIUS;
12302
- return [Math.sin(lambda) * cosPhi * D, -Math.cos(lambda) * cosPhi * D, Math.sin(phi) * D];
12303
- }
12304
- unprojectPosition(xyz) {
12305
- const [x, y, z] = xyz;
12306
- const D = vec3_exports.len(xyz);
12307
- const phi = Math.asin(z / D);
12308
- const lambda = Math.atan2(x, -y);
12309
- const lng = lambda * RADIANS_TO_DEGREES3;
12310
- const lat = phi * RADIANS_TO_DEGREES3;
12311
- const Z = (D / GLOBE_RADIUS - 1) * EARTH_RADIUS;
12312
- return [lng, lat, Z];
12313
- }
12314
- projectFlat(xyz) {
12315
- return xyz;
12316
- }
12317
- unprojectFlat(xyz) {
12318
- return xyz;
12319
- }
12320
- /**
12321
- * Pan the globe using delta-based movement
12322
- * @param coords - the geographic coordinates where the pan started
12323
- * @param pixel - the current screen position
12324
- * @param startPixel - the screen position where the pan started
12325
- * @returns updated viewport options with new longitude/latitude
12326
- */
12327
- panByPosition([startLng, startLat, startZoom], pixel, startPixel) {
12328
- const scale5 = Math.pow(2, this.zoom - zoomAdjust(this.latitude));
12329
- const rotationSpeed = 0.25 / scale5;
12330
- const longitude = startLng + rotationSpeed * (startPixel[0] - pixel[0]);
12331
- let latitude = startLat - rotationSpeed * (startPixel[1] - pixel[1]);
12332
- latitude = Math.max(Math.min(latitude, 90), -90);
12333
- const out = { longitude, latitude, zoom: startZoom - zoomAdjust(startLat) };
12334
- out.zoom += zoomAdjust(out.latitude);
12335
- return out;
12336
- }
12337
- };
12338
- GlobeViewport.displayName = "GlobeViewport";
12339
- function zoomAdjust(latitude, clampToPoles) {
12340
- if (clampToPoles) {
12341
- latitude = Math.max(Math.min(latitude, MAX_LATITUDE), -MAX_LATITUDE);
12342
- }
12343
- const scaleAdjust = Math.PI * Math.cos(latitude * Math.PI / 180);
12344
- return Math.log2(scaleAdjust);
12345
- }
12346
- function transformVector2(matrix, vector) {
12347
- const result = vec4_exports.transformMat4([], vector, matrix);
12348
- vec4_exports.scale(result, result, 1 / result[3]);
12349
- return result;
12350
- }
12351
-
12352
12386
  // ../core/src/transitions/linear-interpolator.ts
12353
12387
  var DEFAULT_PROPS = ["longitude", "latitude", "zoom", "bearing", "pitch"];
12354
12388
  var DEFAULT_REQUIRED_PROPS = ["longitude", "latitude", "zoom"];
@@ -12376,21 +12410,16 @@ void main(void) {
12376
12410
  const result = super.initializeProps(startProps, endProps);
12377
12411
  const { makeViewport, around } = this.opts;
12378
12412
  if (makeViewport && around) {
12379
- const TestViewport = makeViewport(startProps);
12380
- if (TestViewport instanceof GlobeViewport) {
12381
- log_default.warn("around not supported in GlobeView")();
12382
- } else {
12383
- const startViewport = makeViewport(startProps);
12384
- const endViewport = makeViewport(endProps);
12385
- const aroundPosition = startViewport.unproject(around);
12386
- result.start.around = around;
12387
- Object.assign(result.end, {
12388
- around: endViewport.project(aroundPosition),
12389
- aroundPosition,
12390
- width: endProps.width,
12391
- height: endProps.height
12392
- });
12393
- }
12413
+ const startViewport = makeViewport(startProps);
12414
+ const endViewport = makeViewport(endProps);
12415
+ const aroundPosition = startViewport.unproject(around);
12416
+ result.start.around = around;
12417
+ Object.assign(result.end, {
12418
+ around: endViewport.project(aroundPosition),
12419
+ aroundPosition,
12420
+ width: endProps.width,
12421
+ height: endProps.height
12422
+ });
12394
12423
  }
12395
12424
  return result;
12396
12425
  }
@@ -12463,6 +12492,7 @@ void main(void) {
12463
12492
  this.touchRotate = false;
12464
12493
  this.multiTouchDrag = null;
12465
12494
  this.trackpadGesture = false;
12495
+ this.zoomAround = "pointer";
12466
12496
  this.keyboard = true;
12467
12497
  this.transitionManager = new TransitionManager({
12468
12498
  ...opts,
@@ -12556,6 +12586,15 @@ void main(void) {
12556
12586
  const { offsetCenter } = event;
12557
12587
  return [offsetCenter.x - x, offsetCenter.y - y];
12558
12588
  }
12589
+ /** Resolves the zoom anchor for pointer-based controls. */
12590
+ getZoomPosition(position) {
12591
+ if (this.zoomAround === "pointer") {
12592
+ return position;
12593
+ }
12594
+ const viewport = this.makeViewport(this.controllerState.getViewportProps());
12595
+ const [centerX, centerY] = worldToPixels(viewport.center, viewport.pixelProjectionMatrix);
12596
+ return [centerX, centerY];
12597
+ }
12559
12598
  isPointInBounds(pos, event) {
12560
12599
  const { width, height } = this.props;
12561
12600
  if (event && event.handled) {
@@ -12613,6 +12652,7 @@ void main(void) {
12613
12652
  touchRotate = false,
12614
12653
  multiTouchDrag = touchRotate ? "rotate" : null,
12615
12654
  trackpadGesture = false,
12655
+ zoomAround = "pointer",
12616
12656
  keyboard = true
12617
12657
  } = props;
12618
12658
  const isInteractive = Boolean(this.onViewStateChange);
@@ -12635,6 +12675,7 @@ void main(void) {
12635
12675
  this.touchRotate = multiTouchDrag === "rotate";
12636
12676
  this.multiTouchDrag = multiTouchDrag;
12637
12677
  this.trackpadGesture = trackpadGesture;
12678
+ this.zoomAround = zoomAround;
12638
12679
  this.keyboard = keyboard;
12639
12680
  const constraintChanged = !oldProps || oldProps.height !== props.height || oldProps.width !== props.width || oldProps.maxBounds !== props.maxBounds || oldProps.maxBoundsPadding !== props.maxBoundsPadding;
12640
12681
  if (constraintChanged && props.maxBounds) {
@@ -12868,8 +12909,9 @@ void main(void) {
12868
12909
  if (delta < 0 && scale5 !== 0) {
12869
12910
  scale5 = 1 / scale5;
12870
12911
  }
12871
- const transitionProps = smooth ? { ...this._getTransitionProps({ around: pos }), transitionDuration: 250 } : NO_TRANSITION_PROPS;
12872
- const newControllerState = this.controllerState.zoom({ pos, scale: scale5 });
12912
+ const zoomPosition = this.getZoomPosition(pos);
12913
+ const transitionProps = smooth ? { ...this._getTransitionProps({ around: zoomPosition }), transitionDuration: 250 } : NO_TRANSITION_PROPS;
12914
+ const newControllerState = this.controllerState.zoom({ pos: zoomPosition, scale: scale5 });
12873
12915
  this.updateViewport(newControllerState, transitionProps, {
12874
12916
  isZooming: true,
12875
12917
  isPanning: true
@@ -12955,7 +12997,7 @@ void main(void) {
12955
12997
  if (!this.isPointInBounds(pos, event)) {
12956
12998
  return false;
12957
12999
  }
12958
- const newControllerState = this.controllerState.zoomStart({ pos }, this._getConstraintContext("zoom", "start")).rotateStart({ pos }, this._getConstraintContext("rotate", "start"));
13000
+ const newControllerState = this.controllerState.zoomStart({ pos: this.getZoomPosition(pos) }, this._getConstraintContext("zoom", "start")).rotateStart({ pos }, this._getConstraintContext("rotate", "start"));
12959
13001
  pinchEventWorkaround._startPinchRotation = event.rotation;
12960
13002
  pinchEventWorkaround._lastPinchEvent = event;
12961
13003
  this.updateViewport(newControllerState, NO_TRANSITION_PROPS, { isDragging: true });
@@ -12974,7 +13016,7 @@ void main(void) {
12974
13016
  const { scale: scale5 } = event;
12975
13017
  const pos = this.getCenter(event);
12976
13018
  newControllerState = newControllerState.zoom(
12977
- { pos, scale: scale5 },
13019
+ { pos: this.getZoomPosition(pos), scale: scale5 },
12978
13020
  this._getConstraintContext("zoom", "update")
12979
13021
  );
12980
13022
  }
@@ -13002,15 +13044,16 @@ void main(void) {
13002
13044
  const { _lastPinchEvent } = pinchEventWorkaround;
13003
13045
  if (this.touchZoom && inertia && _lastPinchEvent && event.scale !== _lastPinchEvent.scale) {
13004
13046
  const pos = this.getCenter(event);
13047
+ const zoomPosition = this.getZoomPosition(pos);
13005
13048
  let newControllerState = this.controllerState.rotateEnd();
13006
13049
  const z = Math.log2(event.scale);
13007
13050
  const velocityZ = (z - Math.log2(_lastPinchEvent.scale)) / (event.deltaTime - _lastPinchEvent.deltaTime);
13008
13051
  const endScale = Math.pow(2, z + velocityZ * inertia / 2);
13009
- newControllerState = newControllerState.zoom({ pos, scale: endScale }).zoomEnd();
13052
+ newControllerState = newControllerState.zoom({ pos: zoomPosition, scale: endScale }).zoomEnd();
13010
13053
  this.updateViewport(
13011
13054
  newControllerState,
13012
13055
  {
13013
- ...this._getTransitionProps({ around: pos }),
13056
+ ...this._getTransitionProps({ around: zoomPosition }),
13014
13057
  transitionDuration: inertia,
13015
13058
  transitionEasing: INERTIA_EASING
13016
13059
  },
@@ -13055,8 +13098,12 @@ void main(void) {
13055
13098
  return false;
13056
13099
  }
13057
13100
  const isZoomOut = this.isFunctionKeyPressed(event);
13058
- const newControllerState = this.controllerState.zoom({ pos, scale: isZoomOut ? 0.5 : 2 });
13059
- this.updateViewport(newControllerState, this._getTransitionProps({ around: pos }), {
13101
+ const zoomPosition = this.getZoomPosition(pos);
13102
+ const newControllerState = this.controllerState.zoom({
13103
+ pos: zoomPosition,
13104
+ scale: isZoomOut ? 0.5 : 2
13105
+ });
13106
+ this.updateViewport(newControllerState, this._getTransitionProps({ around: zoomPosition }), {
13060
13107
  isZooming: true,
13061
13108
  isPanning: true
13062
13109
  });
@@ -13073,14 +13120,14 @@ void main(void) {
13073
13120
  this._doubleClickDragAnchor = null;
13074
13121
  return false;
13075
13122
  }
13076
- this._doubleClickDragAnchor = pos;
13123
+ this._doubleClickDragAnchor = this.getZoomPosition(pos);
13077
13124
  let newControllerState = this.controllerState.zoomStart(
13078
- { pos },
13125
+ { pos: this._doubleClickDragAnchor },
13079
13126
  this._getConstraintContext("zoom", "start")
13080
13127
  );
13081
13128
  if (event.scale !== 1) {
13082
13129
  newControllerState = newControllerState.zoom(
13083
- { pos, scale: event.scale },
13130
+ { pos: this._doubleClickDragAnchor, scale: event.scale },
13084
13131
  this._getConstraintContext("zoom", "update")
13085
13132
  );
13086
13133
  }